微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

应该以哪个顺序释放分配的内存块?

如何解决应该以哪个顺序释放分配的内存块?

假设如下:

char *a = malloc(m);
char *b = malloc(n);
char *c = malloc(o);

一旦你完成了内存块,这是正确的:

free(a);
free(b);
free(c);

原来是这样:

free(c);
free(b);
free(a);

但必须使用一种或另一种顺序,有选择的依据更令人满意。

是否有任何现有实现对内存碎片或内存释放和后续分配请求满足的速度有任何影响?如果是这样,哪个顺序更有效?还是有其他选择订单的依据?

解决方法

如果这些内存块之间没有任何已知的关系,就没有依据来指定哪个释放顺序是正确的。正如没有依据可以决定哪个分配顺序是正确的。

这不是一个可以先验回答的问题。不释放内存的唯一原因是如果您仍在使用它,并且一块内存可能正在“使用”(即:将指针存储到)另一块内存中。因此,如果不知道内存中发生了什么,就没有理由选择任何特定的释放顺序。

,

通常这应该与大多数用例无关。但是,我曾经有一个项目,该项目分配了非常多的对象,并且在那里产生了显着的性能差异。在这种情况下,第二个变体(从后到前)比按照分配顺序进行释放要快得多。

在我们的场景中,从头到尾释放分配大约需要 4 分钟,而在另一个方向只需要大约 1 分钟。

但与性能一样,更改是否会产生任何差异应该在目标系统上进行衡量。

,

在其他条件相同的情况下,最好按照与获取相反的顺序释放资源。这“感觉”更自然,并且在某些情况下(包括内存释放/分配)实际上可能更有效,其中对称性可以帮助所述资源的管理者更有序地回收它们。

这与为什么例如 C++ 从头到尾构造数组的元素,但以相反的顺序(class.init.general/3)销毁它们的原因相同:

当类对象数组被初始化(显式或隐式)并且元素被构造函数初始化时,应该为数组的每个元素调用构造函数,遵循下标顺序;见dcl.array

[注意 1:数组元素的析构函数按其构造的相反顺序调用。 — 尾注]

,

我喜欢这样想,范围是 ifs

    char *a = malloc(m);
    if (a) {
        char *b = malloc(n);
        if (b) {
            char *c = malloc(o);
            if (c) {
                //...
                free(c);
            }
            free(b);
        }
        free(a);
    }

现在,移除大括号和 ifs ...,您将获得第二个选项。

,

这是一个低级细节,当您的构建环境升级时可能会发生变化。因此,我会关注一般原则而不是具体实现。在这种情况下,我会在一般原则中添加一个假设。

假设:
如果释放内存的顺序对性能有影响,那么构建环境会根据语言的总体趋势选择更好的性能。

这是基于构建环境重视生成快速程序的假设。任何想提出异议的人都应该无视这个答案。

通过“语言的一般趋势”,我指的是最后构建的东西往往首先被破坏的想法。例如,派生类在其基类之后构造,但派生类在其基类之前被销毁。即使在一个类中,成员也会以与构造相反的顺序被销毁。最后建造,首先摧毁。如果成员拥有动态分配的内存,则最后分配,先释放(或多或少)。

这种趋势并不能保证内存会以与获取相反的顺序释放。其实,举出反例并不难。然而,这确实意味着相反的顺序似乎比任何其他顺序更有可能。在考虑程序员可能会做的所有疯狂事情时,几乎没有保证,但在我看来,free 将以对称方式(顺序无关紧要)或针对这种相反顺序进行优化似乎是合理的,如果可能的话。

这不是证明,也不是绝对规则。这只是在玩赔率。如果以上看起来合理,我会建议最初使用语言的趋势。 (实际上,我建议在析构函数中释放内存,这会强制执行语言指定的顺序。)如果分析表明这是一个问题区域,则需要更多关注。在此之前,在问题的场景中,free(c) 首先提高您的赔率。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。