Output error dynamically allocating class objects into a queue template - c++

#include <iostream>
#include "QueueAr.h"
class Test {
int val;
public:
Test(int v)
{val = v;};
int getVal()
{return val;};
};
using namespace std;
int main(int argc, char **argv)
{
Queue<Test*> testStack(4);
for(int i = 0; i < 4; i++) {
Test *t = new Test(5);
testStack.enqueue(t);
delete t;
}
while(!testStack.isEmpty())
cout << (testStack.dequeue())->getVal() << endl;
return 0;
}
So I'm trying to play with the idea of declaring a template class with a data type that is programmer-defined. I decided to go a queue implementation made by the author of my data structures book as the template class.
Now I'm trying to feed some values into it.
I started by creating a Queue object whose data type is a pointer variable to my own class Test. I used a pointer variable because Queue<Test> wasn't working properly for some reason. Next, I came up with the above for loop to make an attempt at initializing, but when I dequeue and display the values, it returns all of them as zero, despite sending 5 to Test's constructor four times in the loop. I believe it might have something to do with the loop, or Test*, but I'm not entirely sure.
Does anyone know what might be wrong here? Thank you in advance.
Also, if anyone needs it, here are the links for the header file "QueueAr.h" and its member functions
https://github.com/rweichler/ecs60/blob/master/p2/src/QueueAr.h
https://github.com/rweichler/ecs60/blob/master/p2/src/QueueAr.cpp

After storing the pointer to Test in your Queue you delete the pointer. This frees the memory and leaves the pointer stored in the Queue dangling, pointing at freed memory. When you dereference this pointer to display the value you can get anything.

Related

How to observe c++ destructor destroys basic data types?

I have two classes one is main and other is Test, for the Test class, I have Test.cpp and Test.h
//-----Test.h--------//
#pragma once
class Test
{
private:
int num;
public:
Test(void);
Test(int n);
~Test(void);
};
//------Test.cpp------//
#include "Test.h"
#include<iostream>
using namespace std;
Test::Test(void)
{
}
Test::Test(int n)
{
num = n;
}
Test::~Test(void)
{
cout << "Deleted" << endl;
cout << "num = " << num << endl ;
}
//---------main.cpp--------------//
#include "Test.h"
#include<iostream>
using namespace std;
int main()
{
Test t1 = Test(5);
return 0;
}
The output which I have expected is
Deleted
num = 0
But Real Output is
Deleted
num = 5
Why this occurs, why destructor, dint free the memory
or dint delete the basic data type, How can I delete the variable,
Using what method I can observe basic datatype getting deleted?
Destruction of an object does not mean setting values to zero. That would be unnecessary work. Rather, all that is required is that resources be released. Bits are typically left as-is (representing 5 in your example) unless there is a compelling reason to do otherwise.
Furthermore, members are destroyed after the class. In your example, first ~Test() is run to destroy t1, then t1.num would be destroyed. The destructor of Test cannot view the destruction of Test::num.
why destructor, dint free the memory or dint delete the basic data type
You did not have any memory allocated in the heap, so there is no need to free anything.
All you have is a basic type int which does not need any memory deallocation.
If instead you had some pointer member variable:
private:
int* num;
and you allocated it somewhere in your constructor: new int(6); then sure you must deallocate/free it inside your destructor.
In this case, probably a shared-pointer may help, which automatically is destroyed just after the destructor:
std::shared_ptr<int> num;
But it has to be constructed, in the constructor you need:
Test::Test(int n)
: num(std::make_shared<int>(n)
{
// *n == 100
}
To see if the data is deleted use Valgrind.

I get an error when trying to make a vector of classes inside of the same class

I am trying to make a class with decendants of the same class, to make a tree, but when i try to access something insode of the vector it never works. i get an exception: std::length_error when trying to access the string.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class A {
public:
string name;
vector<A*> children;
};
int main()
{
A cl;
cl.name= "HI!";
for(int i = 0; i < 10;i++) {
A newCl;
newCl.name= "World!";
cl.children.push_back(&newCl);
}
for(int i = 0; i < 10;i++) {
// error here:
cout << cl.children[i]->name << endl;
}
return 0;
}
Anybody know an easier way to make a tree in C++, or how to fix this?
The problem is in this loop
for(int i = 0; i < 10;i++) {
A newCl;
newCl.name= "World!";
cl.children.push_back(&newCl);
}
The variable newCl will cease to exist at the end of the iteration and you are inserting its address in the vector. When you access it, you are accessing a dangling pointer, this is undefined behavior and your program can crash, produce garbage or anything in between.
You can use heap allocation as proposed by Oblivion, but in such a case you might want to consider the use of smart pointers for memory management.
Otherwise, you can have a vector of values std::vector<A> instead of pointers, possible from C++17 (for more details, see: How can I declare a member vector of the same class?)
Edit: I clarified the use of std::vector<A> after Chipster's comment.
You store reference to a temporary as children:
A newCl;
newCl.name= "World!";
cl.children.push_back(&newCl);
Once you are out of scope the children will dangle.
A* newCl = new A;
Should fix. But you have to go through the vector to free your children.
If you had a reason to use pointers, it is better to use smart pointers:
vector<shared_ptr<A>> children;
Live

How to prevent memory leak when we "have to" pass pointers in loop to some function?

I am having a situation where I have to call a function in loop with pointer (to a class object) as a parameter. Issue is, I cannot modify the signature of that function and that with every iteration of loop, I have to initialize the pointer. This will lead to memory leak as I cannot delete the pointer (after passing it to the function) inside the loop. Is there any way I can prevent memory leak in such a case?
I would like to explain with a simple example:
class testDelete
{
public:
void setValue(int* val) {vec.push_back(val);};
void getValue();
private:
vector <int*> vec;
};
void testDelete::getValue()
{
for (int i=0;i<vec.size();i++)
{
cout << "vec[" << i << "] = " << *vec[i]<<"\n";
}
}
int main()
{
testDelete tD;
int* value = NULL;
for (int i=0;i<10;i++)
{
value=new int(i+1);
/*I am not allowed to change this function's signature, and hence I am forced to pass pointer to it*/
tD.setValue(value);
/*I cannot do delete here otherwise the getValue function will show garbage value*/
//delete value;
}
tD.getValue();
return 0;
}
If deleteTest wants to use pointers of maybe gone objects it should hold std::weak_ptrs.
Holding on to a raw pointer and dereferencing it later is dangerous (unless you can make sure the object is still alive, a.k.a don't use raw but smart pointers).
[...] I cannot modify the signature of that function and that with every
iteration of loop, I have to initialize the pointer. Is there any way I can prevent memory leak in such a case?
If you need dynamically allocated objects, use smart pointers (eg std::smart_ptr for shared ownership). If you do not need to dynamically allocate them then don't.
For the sake of the example lets assume you cannot modify deleteTest, then for integers there is no reason to dynamically allocate anything
int main()
{
std::array<int,10> x;
testDelete tD;
for (int i=0;i<10;i++)
{
x[i] = i+1;
tD.setValue(&x[i]);
}
tD.getValue();
return 0;
}
Take this code with a grain of salt, it is actually deleteTest that needs to be fixed to avoid creating trouble.
TL;DR
In your example you have actually two problems. deleteTest may try to access already gone objects and memory leaks in main. Using smart pointers solves both.
Store the integers in a container:
int main()
{
std::vector<int> values(10);
testDelete tD;
for (int i=0;i<10;i++)
{
values[i] = i + 1;
tD.setValue(&values[i]);
}
tD.getValue();
return 0;
}

Passing object by value and modifying it in C++

The book I'm using wants me to implement LIFO stacks using constructors in C++. The first implementation is fairly easy because it wants me to pass the object in a function by reference (so the code below has an additional & in pushexternal function).
However, I don't know how to properly implement the second version of it. It wants me to make it by passing the object by value. Therefore, it creates a copy of the object and after using a push function on a stack, the pushed element is gone. I don't know how to properly do it when passing it by value. I was thinking about using a copy constructor somehow, but I've tried it and it doesn't seem to work...
This is the code that is written in the book. I'm not supposed to modify it, I can only write my own class / additional functions:
void pushexternal(Stack s, int a) {
s.push(a);
}
int main() {
Stack s;
s.push(0);
s.push(1);
s.push(2);
pushexternal(s, 3);
pushexternal(s, 4);
return 0;
}
And this is a part of my implementation:
#include <iostream>
using namespace std;
class Stack {
public:
int ind;
int * arr;
Stack()
{
arr = new int[25];
ind = -1;
}
~Stack()
{
delete [] arr;
}
void push(int val)
{
arr[++ind] = val;
cout << "Added " << arr[ind] << " to " << ind << endl;
}
};
I'm aware that passing by value is not recommended here, but I'm really wondering how can I make it work properly when pass by value is mandatory. The only thing that comes to my mind is writing some kind of a copy constructor...?
Of course, my code doesn't work here as it makes a copy that is supposed to push a variable, but when passing by value, it's gone when it exits the function...
The results of this program should look like this:
Added 0 to 0
Added 1 to 1
Added 2 to 2
Added 3 to 3
Added 4 to 4
If you were to allocate an extra member in your arr member, you could then use arr[0] instead of ind as your index. That way, even if your stack object is copied by value, the arr pointer will still point to the same memory.
Similar, possibly more complex solutions exist, involving having your object contain a pointer to a structure with both ind and arr in it.

Pointer of class local variable? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Can a local variable's memory be accessed outside its scope?
Is there worrying thing to do a code such (getIDs() returns a pointer):
class Worker{
private:
int workerID;
int departID;
int supervisorID;
public:
Worker()
{
workerID=0;
departID=0;
supervisorID=0;
name="anonymous";
workerAddress="none";
}
void setIDs(int worker, int depart, int supervisor)
{
workerID=worker;
departID=depart;
supervisorID=supervisor;
}
int* getIDs()
{
int id[3];
id[0]=workerID;
id[1]=departID;
id[2]=supervisorID;
return id;
}
};
And then, use it such:
Worker obj;
obj.setIDs(11,22,33);
cout<<(*obj.getIDs())<<endl;
cout<<++(*obj.getIDs())<<endl;
cout<<++(++(*obj.getIDs()))<<endl;
I am wondering about that because the compiler shows:
Warning 1 warning C4172: returning address of local variable or
temporary
Your int id[3] is allocated on a stack and gets destroyed when your int* getIDs() returns.
You're return a pointer to a variable that gets destroyed immediately after getIDs() returns. The pointer then becomes dangling and is practically useless as doing anyting with it is undefined behaviour.
Suppose you defined your class like this:
class Worker{
private:
int IDs[3];
public
// ...
int* getIDs() { return IDs; }
};
This partially solves your problem, as the pointer remains valid as long the Worker object is in scope, but it's still bad practice. Example:
int* ptr;
while (true) {
Worker obj;
obj.setIDs(11,22,33);
ptr = obj.getIDs();
cout << *ptr; // ok, obj is still alive.
break;
} // obj gets destroyed here
cout << *ptr; // NOT ok, dereferencing a dangling pointer
A better way of solving this is to implement your custom operator << for your class. Something like this:
class Worker {
private:
int workerID;
int departID;
int supervisorID;
public:
// ...
friend ostream& operator<<(ostream& out, Worker w);
};
ostream& operator<<(ostream& out, const Worker& w)
{
out << w.workerID << "\n" << w.departID << "\n" << w.supervisorID;
return out;
}
Even if this would work, it wouldn't be good practice to do it this way in c++ unless there is some profound reason why you want pointers to int. Raw c-syle arrays are more difficult to handle than, for instance, std::vectors, so use those, like
std::vector<int> getIDs(){
std::vector<int> id(3);
id[0]=workerID; id[1]=departID; id[2]=supervisorID;
return id;
}
If you're worried about the overhead: this is likely to be optimized away completely by modern compilers.
A local (also caled automatic) variable is destroyed once you leave the function where it is defined. So your pointer will point to this destroyed location, and of course referencing such a location outside the function is incorect and will cause undefined behaviour.
The basic problem here is that when you enter a function call, you get a new frame on your stack (where all your local variables will be kept). Anything that is not dynamically allocated (using new/malloc) in your function will exist in that stack frame, and it gets destroyed when your function returns.
Your function returns a pointer to the start of your 3-element-array which you declared in that stack frame that will go away. So, this is undefined behavior.
While you may get "lucky/unlucky" and still have your data around where the pointer points when you use it, you may also have the opposite happen with this code. Since the space is given up when the stack frame is destroyed, it can be reused - so another part of your code could likely use the memory location where your three elements in that array is stored, which would mean they would have completely different values by the time you dereferenced that pointer.
If you're lucky, your program would just seg-fault/crash so you knew you made a mistake.
Redesign your function to return a structure of 3 ints, a vector, or at the very least (and I don't recommend this), dynamically allocate the array contents with new so it persists after the function call (but you better delete it later or the gremlins will come and get you...).
Edit: My apologies, I completely misread the question. Shouldn't be answering StackOverflow before my coffee.
When you want to return an array, or a pointer rather, there are two routes.
One route: new
int* n = new int[3];
n[0] = 0;
// etc..
return n;
Since n is now a heap object, it is up to YOU to delete it later, if you don't delete it, eventually it will cause memory leaks.
Now, route two is a somewhat easier method I find, but it's kind of riskier. It is where you pass an array in and copy the values in.
void copyIDs(int arr[3] /* or int* arr */)
{
arr[0] = workerID;
/* etc */
}
Now your array is populated, and there was no heap allocation, so no problem.
Edit: Returning a local variable as an address is bad. Why?
Given the function:
int* foo() {
int x = 5;
return &x; // Returns the address (in memory) of x
} // At this point, however, x is popped off the stack, so its address is undefined
// (Garbage)
// So here's our code calling it
int *x = foo(); // points to the garbage memory, might still contain the values we need
// But what if I go ahead and do this?
int bar[100]; // Pushed onto the stack
bool flag = true; // Pushed onto the stack
std::cout << *x << '\n'; // Is this guaranteed to be the value we expect?
Overall, it is too risky. Don't do it.