首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果抛出异常,alloca()是否返回内存?

如果抛出异常,alloca()是否返回内存?
EN

Stack Overflow用户
提问于 2018-12-14 09:59:02
回答 3查看 197关注 0票数 0

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

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

由于泄漏非常明显地绑定到抛出的异常,所以我的理论是,当抛出异常时,alloca()无法释放内存。

这有道理吗?如果是这样的话,我认为它是alloca()中的一个主要缺陷,但是当我google alloca()时,这似乎是一个问题。

我很感谢你对任何专家的见解。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-12-14 10:43:44

这个问题很可能是由于某种程度的间接影响造成的。

字面上的问题是“如果抛出异常,alloca是否返回内存?”。答案是:它只返回--直接分配的内存--。不运行析构函数,alloca-allocated内存中的任何拥有指针都会泄漏。

票数 3
EN

Stack Overflow用户

发布于 2018-12-14 10:15:07

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

尽管通过alloca()分配的空间可能有例外情况下被取消分配(因为通常是通过增加当前堆栈帧的大小来完成的)。这不是标准的一部分,因此我认为你不能保证。

但是--这也意味着对象上的任何适当的析构函数都不会被调用。这意味着,如果对象执行自己的内存管理,这将不会被清除(因为析构函数不会运行来清理它)。

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

代码如下所示:

代码语言:javascript
复制
void func()
{
    MyType* x = (MyType*)alloca(sizeof(MyType));

    passXtoCFunctionThatDoesNotTakeOwnership(x);
}

应该写成这样:

代码语言:javascript
复制
void func()
{
    std::unique_ptr<MyType> x = std::make_unique<MyType>();

    passXtoCFunctionThatDoesNotTakeOwnership(x.get());
}

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

代码语言:javascript
复制
void func()
{
    MyType* x = (MyType*)alloca(sizeof(MyType) * arraySize);

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

那么最好使用std::载体。

代码语言:javascript
复制
void func()
{
    std::vector<MyType> x;
    x.reserve(arraySize);   // or resize() if that is appropriate

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

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

代码语言:javascript
复制
void func()
{
    MyType* x = (MyType*)alloca(sizeof(MyType));

    x->myData = 5;
}

您应该声明一个变量:

代码语言:javascript
复制
void func()
{
    MyType x;

    x.myData = 5;
}
票数 2
EN

Stack Overflow用户

发布于 2018-12-14 10:15:49

来自Linux 男人

…… 因为由alloca()分配的空间是在堆栈帧中分配的,所以如果函数返回的被一个对longjmp(3)或siglongjmp(3)的调用跳过,那么这个空间就会自动释放。 …… 内联代码通常由一条调整堆栈指针的指令组成,不检查堆栈溢出。因此,不存在空错误返回。 . Bugs如果不能扩展堆栈帧,则没有错误指示。(但是,在分配失败后,如果程序试图访问未分配的空间,它很可能接收到一个SIGSEGV信号。)在许多系统中,alloca()不能在函数调用的参数列表中使用,因为由alloca()保留的堆栈空间将出现在函数参数空间的中间。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53777376

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档