如果抛出异常,是否alloca() return 内存?

Does alloca() return memory if an exception is thrown?

我正在维护一个遗留的 C++ 应用程序,它似乎有一个缓慢的内存泄漏。通过确保当前配置不再引发任何异常,我已经设法 "fix" 内存泄漏,并且我还可以触发泄漏并通过配置它以导致许多异常来扩展它。

所有分配的内存都是使用 alloca() 而不是 malloc() 完成的。我得到的解释是,这是因为 alloca() 像 java 垃圾收集器一样工作,并在退出上下文时自动释放内存。

由于泄漏与抛出的异常非常明确,我认为 alloca() 在抛出异常时无法释放内存。

这完全合理吗?如果为真,我觉得它是 alloca() 的一个主要缺陷,但是当我 google alloca() 时,它似乎通常是一个问题。

非常感谢任何专家的见解。

在 C++ 中,您不应使用 C 内存管理例程。在现代 C++ 中,智能指针为您提供细粒度的确定性垃圾收集。

虽然通过 alloca() 分配的 space 可能会被异常释放(因为它通常是通过增加当前堆栈帧的大小来完成的)。这不是标准的一部分,因此我认为您不能做出任何保证。

BUT 这也意味着永远不会调用对象上的任何适当的析构函数。这意味着如果对象进行自己的内存管理,则不会被清理(因为析构函数不会 运行 清理它)。

虽然alloca()可能很快。我认为它为内存管理增加的额外负担(在一般情况下)是不值得的;不过,如果您特别需要额外的速度,那可能是值得的。

代码看起来像这样:

void func()
{
    MyType* x = (MyType*)alloca(sizeof(MyType));

    passXtoCFunctionThatDoesNotTakeOwnership(x);
}

应该这样写:

void func()
{
    std::unique_ptr<MyType> x = std::make_unique<MyType>();

    passXtoCFunctionThatDoesNotTakeOwnership(x.get());
}

如果您使用它来保存对象数组。

void func()
{
    MyType* x = (MyType*)alloca(sizeof(MyType) * arraySize);

    // STUFF
    x[0].stuff();
}

那么最好用一个std::vector

void func()
{
    std::vector<MyType> x;
    x.reserve(arraySize);   // or resize() if that is appropriate

    // STUFF
    x[0].stuff();
}

如果您将它用于简单的对象。那么你应该只声明自动变量:

void func()
{
    MyType* x = (MyType*)alloca(sizeof(MyType));

    x->myData = 5;
}

您应该只声​​明一个变量:

void func()
{
    MyType x;

    x.myData = 5;
}

来自 Linux man

....

Because the space allocated by alloca() is allocated within the stack frame, that space is automatically freed if the function return is jumped over by a call to longjmp(3) or siglongjmp(3).

....

The inlined code often consists of a single instruction adjusting the stack pointer, and does not check for stack overflow. Thus, there is no NULL error return.

.....

Bugs There is no error indication if the stack frame cannot be extended. (However, after a failed allocation, the program is likely to receive a SIGSEGV signal if it attempts to access the unallocated space.) On many systems alloca() cannot be used inside the list of arguments of a function call, because the stack space reserved by alloca() would appear on the stack in the middle of the space for the function arguments.

这样对于栈帧中alloca分配的内存,异常不会导致内存泄漏。但是,与任何异常一样,这可能导致堆内存泄漏,因为将跳过放置在 alloca 之后的析构函数和内存释放方法。

问题很可能是由于间接级别造成的。

字面问题是"does alloca return memory if an exception is thrown?"。答案是;它returns只是直接分配的内存。没有析构函数 运行,alloca 分配的内存中的任何拥有指针都已泄漏。