This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is The Rule of Three?
I have the a problem of the double freeing of memory in the following program.
The debugger shows that the issue is in the push_back() function.
Class A:
class A {
public:
A(int x);
int x;
};
A::A(int x) {
this->x = x;
}
Class B:
class B {
public:
B(int x);
~B();
A* a;
};
B::B(int x) {
this->a = new A(x);
}
B::~B() {
delete a;
}
Main function:
int main() {
vector<B> vec;
for(int i = 0; i < 10; i++) {
vec.push_back(B(i)); <------------ Issue is here
}
cout << "adding complete" << endl;
for(int i = 0; i < 10; i++) {
cout << "x = " << (vec[i].a)->x << endl;
}
return 0;
}
What is wrong in this code?
EDIT: Error double free or memory corruption
You forgot to define a copy constructor and copy assignment operator, so your wrapped object is being deleted by some B.... then again when some copy of B goes out of scope.
In this case it's the B(i) temporary on the line you've identified, as well as an implementation-defined number of copies within the vector.
Abide by the rule of three.
The problem in your code is due to the fact that "plain" C/C++ pointers have no concept of ownership. When a pointer gets copied, both copies* "think" that they own the data, leading to double-deletion.
In recognition of this fact, the designers of the C++ standard library introduced a unique_ptr<T> class that helps you address problems like that.
* One copy of the pointer is in the instance of B passed to push_back; the other copy of the pointer is in the instance entered into the vector.
Heed the Rule of Three
Everyone else has already harped on this so I won't dive further.
To address the usage you are apparently trying to accomplish (and conform to the Rule of Three in the process of elimination), try the following. While everyone is absolutely correct about proper management of ownership of dynamic members, your specific sample can easily be made to avoid their use entirely.
Class A
class A {
public:
A(int x);
int x;
};
A::A(int x)
: x(x)
{
}
Class B
class B {
public:
B(int x);
A a;
};
B::B(int x)
: a(x)
{
}
Main Program
int main() {
vector<B> vec;
for(int i = 0; i < 10; i++) {
vec.push_back(B(i));
}
cout << "adding complete" << endl;
for(int i = 0; i < 10; i++) {
cout << "x = " << vec[i].a.x << endl;
}
return 0;
}
Bottom Line
Don't use dynamic allocation unless you have a good reason to, and it is lifetime-guarded by contained variables such as smart pointers or classes that vigorously practice the Rule of Three.
Related
If I have a class with members like this:
class MyClass {
public:
void set_my_vector() {
for (int ind = 0; ind < 3; ++ind) {
my_vector.push_back(new MyStruct(i, i*2));
}
}
private:
struct MyStruct {
int num_a;
int num_b;
MyStruct(int i, int j) : num_a(i), num_b(j) {}
};
std::vector<MyStruct*> my_vector;
};
Do I need to write the rule-of-five functions, or will std::vector take care of deep copying and deleting the elements allocated on the heap?
EDIT:
The following code uses default copy constructor, so I assume that after I copy my_class1 object into my_class2 object, the elements of my_class1.my_vector and my_class2.my_vector will be the same, because the MyStruct pointers were copied, but not the data itself. However, the output shows that they are not the same. You can run the code here: https://onlinegdb.com/S1pK9YE4v
#include <iostream>
#include <vector>
class MyClass {
public:
void fill_my_vector(int i, int j) {
my_vector.clear();
for (int ind = 0; ind < 3; ++ind) {
my_vector.push_back(new MyStruct(i, j));
}
}
void print () {
for (int ind = 0; ind < 3; ++ind) {
std::cout << my_vector[ind]->int1 << ", " << my_vector[ind]->int2 << std::endl;
}
std::cout << std::endl;
}
private:
struct MyStruct {
MyStruct (int i, int j) :
int1(i), int2(j)
{}
int int1;
int int2;
};
std::vector<MyStruct*> my_vector;
};
int main()
{
MyClass my_class1;
my_class1.fill_my_vector(42, 43);
std::cout << "my_class1: " << std::endl;
my_class1.print();
MyClass my_class2 = my_class1;
my_class2.fill_my_vector(12, 13);
std::cout << "my_class2: " << std::endl;
my_class2.print();
std::cout << "my_class1: " << std::endl;
my_class1.print();
}
EDIT2: I know about smart pointers. I am specifically interested what happens if I use raw pointers.
You need to implement the copy constructor, copy assignment and destructor.
Additionally, consider changing your vector declaration from
std::vector<MyStruct*> my_vector;
to
std::vector<std::unique_ptr<MyStruct>> my_vector;
so that it actually owns the heap allocated objects properly. Doing this change will help you not write a destructor.
No, std::vector doesn't take care of deep copying of your objects stored by pointer. You have few possibilities to solve this:
Store MyStruct by value.
Store std::unique_ptr<MyStruct>.
Store std::shared_ptr<MyStruct>.
Note that because MyStruct contains only fields of the primitive types, neither of copy constructor, assignment operator and destructor are needed, otherwise you'd have to implement them, default implementation which compiler will generate automatically will be good enough.
I know this question is already answered. But I just want to confirm what I understand.
Here is my snippet code. It comes from this.
#include <iostream>
using namespace std;
class Base
{
void a() { cout << "a "; }
void c() { cout << "c "; }
void e() { cout << "e "; }
// 2. Steps requiring peculiar implementations are "placeholders" in base class
virtual void ph1() = 0;
virtual void ph2() = 0;
public:
// 1. Standardize the skeleton of an algorithm in a base class "template method"
virtual ~Base() = default;
void execute()
{
a();
ph1();
c();
ph2();
e();
}
};
class One: public Base
{
// 3. Derived classes implement placeholder methods
/*virtual*/ void ph1() { cout << "b "; }
/*virtual*/ void ph2() { cout << "d "; }
};
class Two: public Base
{
/*virtual*/ void ph1() { cout << "2 "; }
/*virtual*/ void ph2() { cout << "4 "; }
};
int main()
{
Base *array[] =
{
&One(), &Two()
};
for (int i = 0; i < 2; i++)
{
array[i]->execute();
cout << '\n';
}
}
When I compiled, it gives the error as the title:
error: taking address of temporary [-fpermissive]
&One(), &Two()
error: taking address of temporary [-fpermissive]
&One(), &Two()
So, I try to find in the internet. And as they said:
&A() is creating a temporary object which gets destructed on exit of the full expression automagically...
When I changed error line
&One(), &Two()
to
new One(), new Two()
Then, it works.
But, how I make the origin code works like the author wrote? Should I use delete like
delete array[i];
With modern C++ features (11 and above) you can handle such polymorphic arrays with std::vector<std::unique_ptr<Base>>. vector allows automatic destruction and extension, and unique_ptr will destroy the object on its own destruction:
std::vector<std::unique_ptr<Base>> array;
array.emplace_back(new One());
array.emplace_back(new Two());
for(auto &p : array)
p->execute();
// no explicit cleanup is required here
You can choose other smart pointer classes as vector's elements, or even use std::array as fixed size container, but general idea is same for all approaches:
Try not to handle memory management manually, use STL primitives for
such low-level actions.
First time posting on here, and I'm not a CS guy, so please bear with me. I have a good sized, code, so I will post a bare-bones version of my problem below and then explain it.
#include <vector>
#include <memory>
class A{
public:
A(){};
double dbl[20];
};
typedef std::shared_ptr<A> A_ptr;
class B{
public:
const std::vector<A_ptr> createAVector(){
std::vector<A_ptr> vec;
for(int i=0; i<4; i++){
vec.push_back(A_ptr( new A() ));
}
return vec;
}
};
int myfunc(){
// Do Stuff...
std::vector<A_ptr> globvec;
B b;
for(int i=0; i<1e6; i++){
const std::vector<A_ptr> locvec = b.createAVector();
for(int i=0; i<locvec.size(); i++) globvec.push_back(locvec[i]);
}
globvec.clear();
globvec.shrink_to_fit();
// Do more stuff...
return 1;
}
int main(){
myfunc();
for(auto i=0; i<3; i++){
myfunc();
}
return 1;
}
Edit: I modified the code so it actually compiles.
So, basically I have two classes. Class A stores the actual data. Class B, among other things, creats a vector of std::shared_ptrs to A and returns it. I then assemble these local vectors into a large global vector in a function called myfunc. To test that memory is freed when I want to shrink the size of globA, I call globA.clear() and globA.shrink_to_fit().
The problem is that calling clear() and shrink_to_fit() does not free the memory of all the A's created.
Am I doing something obviously wrong here? Any idea what might be going on?
Any help would be greatly appreciated.
Thanks!
John
Your code is fine. You can essentially 'prove' that you are not leaking A objects with this... (I also had to reduce the number of iterations from 1e6 to get any reasonable runtime).
There are more sophisticated tools for finding memory leaks. I know for Linux we use Valgrind. I don't know what the Windows equivalent is however.
class A{
public:
A() { std::cout << "Created A " << ++num_instances << std::endl;}
~A() { std::cout << "Destroyed A " << --num_instances << std::endl;}
static int num_instances; // So not thread-safe
double dbl[20];
};
int A::num_instances = 0;
Consider this code snippet:
#include <iostream>
using namespace std;
class X {
public:
class Z {
public:
void f() {
cout << "Z().f()" << endl;
}
};
class Y {
public:
int A;
Y(int x) {
A = x;
}
int c() {
return A;
}
};
public:
Z* z;
// How to free Y instance ?
Y* a(int x) {
Y* y = new Y(x);
return y;
}
public:
X() {
z = new Z();
}
~X() {
delete z;
}
};
int main(void) {
int a;
X* x = new X();
cout << "input :" << endl;
cin >> a;
cout << "result : " << x->a(a)->c() << endl;
x->z->f();
delete x;
return 0;
}
While Z object can easily be freed on ~X(), i am curious how to free Y one ? Since i am not assigning any variable to hold its memory address.
Btw, what's the terminology for something like this ? x->a(a)->c()
Thank you. :)
// How to free Y instance ?
Y* a(int x) {
Y* y = new Y(x);
return y;
}
Well, the problem is that it is not clear from the function prototype who is responsible for deleting the instance. But since only the caller has a handle to the instance, then it should be the called's responsibility to delete. This should be well documented. But the best approach would be to use a smart pointer with the right ownership semantics. In this case, std::unique_ptr<Y> seems like an appropriate match, and the mere fact of using it makes the intent clear, removing the need for documentation concerning ownership:
std::unique_ptr<Y> a(int x)
{
return std::unique_ptr<Y>( new Y(x) );
}
You're returning the memory from the function, so it is up to the caller to delete it:
X x;
Y *ptr = x.a(5);
delete ptr;
Hopefully you never have to do something like this. If you must then it's recommended that you use smart pointers like a shared_ptr or unique_ptr.
std::unique_ptr<Y> a(int x) {
return std::unique_ptr<Y>(new Y(x));
}
With this, you never have to worry about deleting the instance as the destructor of the pointer class holds that responsibility.
This is related to a question posted yesterday.
class A
{
public:
mutable int x;
A()
{
static int i = 0;
x = i;
i++;
std::cout << " A()" << std::endl;
}
~A()
{
std::cout << "~A()" << std::endl;
}
void foo() const
{
x = 1;
};
};
class B
{
public:
const A & a;
B(const A & a) : a(a)
{
std::cout << " B()" << std::endl;
}
~B()
{
std::cout << "~B()" << std::endl;
}
void doSomething()
{
a.foo();
};
};
int main()
{
B b((A()));
b.doSomething();
}
Now, a's destructor is called before the call to doSomething. However, the call works although the function basically changes a member of A. Is it not the same instance. No other A's are created. I used the static inside A's constructor to keep track of that. Can anyone explain?
This is undefined behavior, so there is no language standard explanation.
However, the destructor of A doesn't do anything to the memory area where x is stored, so if you look there later the value might just still be there. Or if you try to write to the address, the address is still there. You are just not allowed to do that.
Bo is correct.
In addition, you could check the address where 'A' is stored, and that should confirm that that address simply hasn't been reused yet (keep in mind a destructor frees ("releases") the memory, but doesn't traverse the data structure setting all of the bits back to 0; that would be inefficient).
If, for example, you find that A is stored on top of the stack, then you are simply fortunate that your subsequent function call doesn't pass in a parameter, as that would overwrite A's memory region.
Your reference is invalid after ~A() and it is undefined behavior
~A() calls destructors of all members of A in addition
Try so for example
class B
{
public:
const std::string & a;
B(const std::string & a) : a(a)
{
std::cout << " B()" << std::endl;
}
~B()
{
std::cout << "~B()" << std::endl;
}
void doSomething()
{
std::cout << "a = " << a << std::endl;
};
};
int main()
{
B b(std::string("I love C++ so much!"));
b.doSomething();
}
Expanding on Bo's answer.
For a temporary to exist, space will be reserved on the stack. This space is actually reserved as long as the semantics require the temporary to exist, and may then be reuse for something else.
If you were trying to use the memory after it has been reused, you would observe a strange behavior (the very definition of undefined behavior being that anything can happen). As it is, you luck out and the memory is still there, in the state you expect it to.
Example:
#include <iostream>
struct A {
A(): p(0) {}
~A() { if (p) { std::cout << *p << "\n"; } }
int* p;
};
int bar0();
void bar1(int i);
int main() {
A a;
{
int x = 4; a.p = &x;
}
{
int y = bar0(); bar1(y);
}
}
int bar0() { return 7; }
void bar1(int i) { std::cout << i << "\n"; }
Here, the compiler may choose to reuse the space of x for y, or just do anything it wants, and thus you're actually printing garbage.
Here is gcc 4.3.4 (and 4.5.1) output (courtesy of ideone):
7
4
Meaning that the space is not reused with those...