堆栈或堆在不正确的堆分配中

时间:2016-11-10 21:34:14

标签: c++ c++11 c++14

在场景1中的堆栈或堆上是funcVar吗?

我问,因为我怀疑它是,因此这可能是一种做事以减少内存泄漏的好方法。也就是说,最好给出一些自动分配位置,然后将代码放在堆上的更高级别,这样可以间接地在堆上放置较低级别的代码,如方案1中那样。

在方案2中,可能永远不会调用删除。通过使用方案1中的代码,我希望尽可能减少(不消除)方案2中的问题。

情景1

class Test{
    int memVar = 1;

    void func(){
        int funcVar = 2;
        SomeClass::someFuncThatCouldCrash();
    }
};

Test* t = new Test();

场景2

class Test{
    int memVar = 1;

    void func(){
        int* funcVar = new int(2);
        SomeClass::someFuncThatCouldCrash();
        delete funcVar;   //May not free due to crash in line above;
    }
};

Test t;  //or Test* t = new Test()

3 个答案:

答案 0 :(得分:1)

在方案1中funcVar(假设它是int funcVar = 2)在调用func()时位于堆栈上,而在方案2中它位于堆上。你是对的,如果someFuncThatCouldCrash抛出异常就永远不会被删除。

此外,在方案2中,您删除funcVar然后将其返回..这没有用。同样在这种情况下,当返回类型是常规int时返回指针。

在C ++ 11中,您不希望处理raw new和delete。基本上,大多数应该是堆栈上的变量。如果需要堆分配,请使用类似向量的内容,该向量是堆栈中的局部变量,用于在内部管理堆分配。这样,当向量离开作用域时,它会自行清理而不必调用delete。如果您想进一步查找,这称为RAII(资源分配是初始化)。

如果您确实需要指向对象的指针(例如通过基类指针保存多态对象,或者通常创建大类的实例),那么您希望std::unique_ptr基本上创建该局部变量负责在您创建的对象上调用delete。在极少数情况下,您可能还需要std::shared_ptr,但如果需要,您可以查看它的作用以及为什么需要它。

答案 1 :(得分:0)

在第一个场景中,它在堆栈上分配。在第二种情况下,它是在堆上分配的,如果从SomeClass::someFuncThatCouldCrash抛出一个异常进入堆栈的异常,那么它是正确的。

如果您想保持内存安全但使用动态分配,则应根据用例使用std::unique_ptrstd::shared_ptr

答案 2 :(得分:0)

自动存储中的局部变量位于“堆栈”上。

类成员变量位于“堆栈”或“堆”上,具体取决于类的实例是在“堆栈”还是“堆”上。

全局数据(包括静态局部变量和静态类成员变量)既不在“堆栈”也不在“堆”中。

线程本地数据既不在“堆栈”中,也不在“堆”中(但可以在堆上实现)。

所以场景1有funcVar作为局部变量,因此在“堆栈”上。类Test的实例在堆上。

在方案2中,funcVar仍然在“堆栈”上,但它指向的内容是“堆”上的内容。这确实不是例外;如果抛出异常,它可能会泄漏。崩溃将在几乎任何操作系统上清理任何“剩余”的简单内存资源。在某些情况下,有些情况下您可以获得的资源在流程退出时不会被回收,但它们不是mallocnew返回的资源。

使用std::unique_ptrstd::make_unique可以减轻几乎所有此类泄漏。在现代C ++中,避免原始指针分配和类型系统中未明确拥有的内存资源通常被认为是一个好主意。