2014-07-17 33 views
0

我试图回答this问题,所以我决定创建以下简单的测试用例,以便OP可以自己看到内存泄漏。为什么这里没有内存泄漏

#include<iostream> 

class MyObject 
{ 
public: 
    MyObject(){std::cout << "creation of my object" << std::endl;} 
    virtual ~MyObject(){std::cout << "destruction of my object" << std::endl;} 
}; 

void processMyObject(MyObject foo) 
{ 
} 

int main() 
{ 
    processMyObject(*new MyObject()); 
    return 0; 
} 

我编译它:

g++ test.cpp -o test 

然后,我看到了一个意想不到的输出:

creation of my object 
destruction of my object 

我是绝对没有这里发生了什么的想法。任何人都可以向我解释?

PS:我因为你的价值采取MyObject使用G ++ 4.6.3

+6

有内存泄漏。你需要测试拷贝并移动拷贝构造函数。 – juanchopanza

回答

6

既然你通过值传递一个对象到函数中,您会产生一个副本或移动复制构造。但是你没有跟踪你原始的内存泄漏检查器。你可以提供自己的拷贝构造函数,然后你会看到正在创建两个对象,只有一个被破坏:

#include<iostream> 

class MyObject 
{ 
public: 
    MyObject() {std::cout << "creation of my object" << std::endl;} 
    MyObject(const MyObject&) {std::cout << "copy creation of my object" << std::endl;} 
    ~MyObject() {std::cout << "destruction of my object" << std::endl;} 
}; 

void processMyObject(MyObject foo) {} 

int main() 
{ 
    processMyObject(*new MyObject()); 
} 

输出:

creation of my object 
copy creation of my object 
destruction of my object 
4

因此存在破坏。但是processMyObject末尾的foo参数被破坏。

*new确实在这种情况下仍然泄漏。

编辑:正如juanchopanza指出的那样,您还需要在复制构造函数和移动构造函数中打印语句。

+0

正确 - 只是指出为什么我们只得到一个(明显的)构造函数调用... – doctorlove

+0

@doctorlove其实,它在评论中被指出。我编辑提到它:) – JBL

+0

哦,现在我明白了。我有点惭愧,我自己找不到它。谢谢 ! –

1

实际上存在内存泄漏。仅仅因为你的物品被摧毁了,并不意味着你删除了你用new获得的资源。您必须明确使用delete

编辑

所以这里发生的事情:

  1. 要调用的飞行默认的构造函数,并将它传递给函数调用。这将打印第一条消息。
  2. 作为函数调用的一部分,该对象正在传递到processMyObject(),使用已由编译器隐式定义的复制构造函数在该范围内创建一个新对象。
  3. 当该对象(位于processMyObject())超出范围时,将调用其析构函数,打印第二条消息。

因此,打印第一条消息的实例与打印第二条消息的实例不同。

希望能够解决问题。

+1

是的,但问题是为什么我们可以看到被删除的内容? – doctorlove

3

在你的代码会发生什么

  • 您构造一个对象并获得其(creation of my object
  • 信息,你把它传递给函数 - 拷贝构造函数的火灾,但没有报告任何
  • 副本被破坏 - 你得到的信息(destruction of my object
  • 原始实例泄漏尽管事实上,你没有任何有关它的信息。

如何看?

只是报告施工和销毁过程中指针this(quick'n'dirty,请不要抱怨):

class MyObject 
{ 
public: 
    MyObject(){std::cout << "creation of my object (" << (int)this << ")" << std::endl;} 
    virtual ~MyObject(){std::cout << "destruction of my object (" << (int)this << ")" << std::endl;} 
}; 

结果:

creation of my object (165437448) 
destruction of my object (-1076708692) 

正如你看到的,销毁的对象与创建的不同。

如何“修复”它显示泄漏?

最简单的方法“修理”你的代码是通过指针传递对象:

#include<iostream> 

class MyObject 
{ 
public: 
    MyObject(){std::cout << "creation of my object" << std::endl;} 
    virtual ~MyObject(){std::cout << "destruction of my object" << std::endl;} 
}; 

void processMyObject(MyObject * foo) 
{ 
} 

int main() 
{ 
    processMyObject(new MyObject()); 
    return 0; 
} 

另一种选择是报告副本构建函数和移动构建函数以及:

class MyObject 
{ 
public: 
    MyObject(){std::cout << "creation of my object" << std::endl;} 
    MyObject(const MyObject & obj) { std::cout << "copy-ctor" << std::endl; } 
    MyObject(MyObject && obj) { std::cout << "move-ctor" << std::endl; } 
    virtual ~MyObject(){std::cout << "destruction of my object" << std::endl;} 
}; 
+1

@doctorlove我也在那里发布了答案。将指针与构造/销毁报告一起打印是一种简单且强大的跟踪内存泄漏的方法:) – Spook