堆栈销毁期间自动堆​​清理

时间:2011-04-14 18:42:30

标签: c++ c memory allocation

int* f()
{
    int *p = new int[10];
    return p;
}

int main()
{
    int *p = f();
    //using p;
    return 0;
}

在堆栈破坏期间,当函数返回它的值时,某些编译器(在我被告知时隐含的VS或gcc等常见的那些)可能会尝试自动释放本地指针(例如p)所指向的内存吗?即使不是,我能否正常删除[]中分配的内存?问题似乎是那时关于精确数组大小的信息丢失了。另外,如果是malloc和free,答案是否会改变?

谢谢。

6 个答案:

答案 0 :(得分:7)

仅销毁释放本地变量。

在您的情况下,p被“销毁”(已发布),但p指向的内容是“已销毁”(使用delete[]发布的内容)。

是的,您可以,并且/必须/必须在您的主要使用delete[]。但这并不意味着在C++中使用原始指针。您可能会发现这本电子书很有趣:Link-Alf-Book

如果你想delete当函数“超过”(超出范围)时局部变量指向的是什么,请使用std::auto_ptr()(仅适用于非数组变量,而不适用于非数组变量)需要delete[]

  

此外,答案会改变以防万一   malloc和free?

不,但你应该确保不混合free()/new/delete/malloc()。这同样适用于new/delete[]new[]/delete

答案 1 :(得分:3)

不,他们不会freedelete指针指向的内容。它们只会释放指针本身占用的几个字节。我认为,调用freedelete的编译器会违反语言标准。

如果指向内存的指针,即delete[]的结果,您将只能main f()内存。您不需要跟踪分配的大小; newmalloc在幕后为您做这件事。

如果您希望在函数返回时清理内存,请使用智能指针,例如boost::scoped_ptrboost::scoped_array(均来自Boost库集合),std::auto_ptr(在当前的C ++标准中,但即将被弃用)或std::unique_ptr(在即将推出的标准中)。

在C中,无法创建智能指针。

答案 2 :(得分:2)

  

在堆栈破坏期间,当函数返回它的值时,某些编译器(当我被告知时,隐含的VS或gcc等常见的那些)可能会尝试自动释放本地指针(例如p)所指向的内存吗? / p>

简答:否

长答案:

如果你使用智能指针或容器(就像你应该的那样),那么是的 当智能指针超出范围时,内存将被释放。

std::auto_ptr<int> f()
{
    int *p = new int;
    return p; // smart pointer credated here and returned.
              // p should probably have been a smart pointer to start with
              // But feeling lazy this morning.
}

std::vector<int> f1()
{
    // If you want to allocate an array use a std::vector (or std::array from C++0x)
    return std::vector<int>(10);
}

int main()
{
    std::auto_ptr<int> p = f();
    std::vector<int>   p1 = f1();

    //using p;
    return 0;  // p destroyed
}
  

即使不是,我能否正常删除[]中已分配的内存?

一旦不需要,确保正确释放所有内存是正常的 注意delete []delete不同,因此请谨慎使用它们。

分配有new的内存必须与delete一起发布 分配有new []的内存必须与delete []一起发布 分配有malloc/calloc/realloc的内存必须与free一起发布。

  

问题似乎是那时关于精确数组大小的信息丢失了。

记住此信息是运行时系统问题。如何存储它不是由标准指定的,但通常它接近于已分配的对象。

  

另外,如果是malloc和free,答案是否会改变?

在C ++中,您可能不应该使用malloc / free。但他们可以使用。当它们被使用时,你应该一起使用它们以确保内存不会泄漏。

答案 3 :(得分:0)

你被误导了 - 局部变量被清理了,但是分配给本地指针的内存却没有。如果你没有返回指针,你会立即发生内存泄漏。

不要担心编译器如何跟踪分配的元素数量,这是C ++标准未解决的实现细节。只知道它有效。 (只要你使用delete[]表示法,你做了)

答案 4 :(得分:0)

我没有听说过编译器会这样做,但编译器当然可以检测(在很多情况下)函数中分配的内存是否不再被指针引用,然后释放该内存。

但是,在你的情况下,内存不会丢失,因为你保留了一个指向它的指针,这是函数的返回值。

内存泄漏的一个非常常见的情况是此代码的完美候选者:

int *f()
{
    int *p = new int[10];
    // do something that doesn't pass p to external
    // functions or assign p to global data
    return p;
}

int main()
{
    while (1) {
      f();
    }
    return 0;
}

正如您所注意到的,指向已分配内存的指针已丢失,编译器可以绝对确定地检测到该指针。

答案 5 :(得分:0)

当您使用new[]时,编译器会添加额外的簿记信息,以便它知道delete[]的元素数量。 (以类似的方式,当你使用malloc时,它知道free有多少字节。一些编译器库提供扩展来找出那个大小。)