2011-06-20 116 views
0

我有一个关于我的C++代码中的内存管理的一般问题。编译器抱怨说,当我用一个指向我已经在堆栈上动态初始化的对象的新指针替换指向对象的指针时,存在潜在的内存泄漏。例如:C++指针和堆栈内存管理

int* foo(int* h){ 
int* b = new int(5); 
b = h; //Memory leak here. How do I delete b without creating a dangling pointer? 
return b; 
} 

然后我用这个功能来改变指针

int i = 1; int* c = &i; foo(c);

的状态所以我的问题是我有一个具有类似于上面的一个函数的类。 什么时候可以从foo函数中删除b?

delete b; 

将这个进入析构函数(这不会帮助我,因为我使用的时间函数foo的负荷。因此堆将得到可能使用起来....?)

如果我上面没有提供足够的信息。请告诉我。

+2

让我们从基础开始:你的函数'foo'不修改值由它的参数指向的。它应该做什么? – Jon

+0

'foo(c);'不要做任何事'c' – rmflow

+0

老实说,我不明白你的问题..但存在内存泄漏的风险,例如:foo(new int);这里int会在你调用foo时泄漏 –

回答

2

由于这是一个普遍的问题,我首选的一般方法是使用智能指针,在你的班级中使用RAII进行处理。

智能指针封装了原始指针,并为您处理所需的内存管理 - 当您的类被破坏时,无论指针值在哪里被保存,都将被清除而不必手动删除它。当您为智能指针分配一个新值时,它会自动删除您的现有值(如果有的话)。

boost::scoped_ptr作为班级成员应该在这里适合你。

这里似乎也有困惑,关于什么是在堆栈上和什么是在堆上。您不会因为您一遍又一遍地调用foo(除非递归到foo无界,在这种情况下最终会用完堆栈空间)而用完堆栈。您的本地变量b位于堆栈上,但它指向在堆上使用new分配的内存。当您退出foo时,堆栈将重置为调用功能 - 用于b的堆栈内存现在可用于其调用的下一个功能 - 但仍需要保留b指向的堆内存的所有权(并最终释放)。

编辑:一些示例代码应该澄清的智能指针的方法

class MyClass { 
public: 
    MyClass() {} // no explicit init for myPointer needed 
    ~MyClass() {} // frees up any pointer held in myPointer, no explicit delete needed 

    void Foo(int* c) 
    { 
    myPointer.reset(c); // releases any existing value, takes ownership of c 
    } 

private: 
    boost::scoped_ptr<int> myPointer; // initially empty 
}; 
+0

嗨史蒂夫。最后一段是我问的问题。只是从来没有制定过它。我怎样才能从堆中释放内存而不会成为悬挂指针?或者这不会发生?再次感谢! – MWright

+0

我已经添加了一些代码来澄清,希望这有助于。智能指针和RAII是提高C++生产力和代码质量的关键部分。理解封面下面发生的事情很重要,以及如何在原始问题中手动使用'new/delete'来完成。 –

+0

谢谢史蒂夫,这太棒了!提升是STL的一部分还是我需要一个库?这是非常C#ish – MWright

3

如果你真的想在函数分配一个新的指针来代替指针的值,我会建议使用一个参考:

void SomeClass::foo(int*& h) 
{ 
    delete h; 
    h = new int(5); 
} 

当然,如果你有一个指针调用它,这将打破一个int这是不是在堆上,因为你不能delete它在那种情况下。所以不要这样做。

+0

嗨放松。我改变了我的功能?删除b在哪里?在函数中设置h之后还是会导致h成为悬挂指针? – MWright