【问题标题】:Trying to understand memory leaks with NULL in c试图理解 c 中的 NULL 内存泄漏
【发布时间】:2020-03-27 05:36:54
【问题描述】:

我创建了一个小测试来创建内存泄漏并使用leaks 命令测试终端中的泄漏。现在我遇到了一个奇怪的 NULL 行为。那么任何解释为什么其他代码泄漏,而另一个没有?他们真的不一样吗?


int     main(void)
{
    char *ptr;
    char *btr;

    ptr = NULL;
    btr = (char*)malloc(4);
    btr = ptr;
    while (1)
        ;
    return (0);
}
    // LEAKS

int     main(void)
{
    char *btr;

    btr = (char*)malloc(4);
    btr = NULL;
    while (1)
        ;
    return (0);
}
    //NO LEAKS ?? why

【问题讨论】:

  • 你是如何检查泄漏的?
  • 究竟是什么决定了“泄漏”与“无泄漏”?看来要么是你欺骗了你的分析器,要么是一些编译器优化使代码变得不同。
  • 另外,不要转换malloc的返回值。 stackoverflow.com/questions/605845/…(与问题无关)
  • 您如何确定泄漏?您是否考虑编译器优化?
  • 我猜你正在使用 OS X leaks 命令?

标签: c pointers memory-management memory-leaks null


【解决方案1】:

很遗憾我无法发表评论,但有人评论说这将是编译器优化的结果。

但是,如果我们复制原始的非泄漏代码并将值更改为更大的数字,我们可以清楚地看到它正在分配内存:

int     main(void)
{
    char *btr;

    btr = (char*)malloc(1000000);
    btr = NULL;
    while (1)
        ;
    return (0);
}

泄漏输出:

Process 9945: 162 nodes malloced for 994 KB
Process 9945: 0 leaks for 0 total leaked bytes.

如果我们将分配注释掉:

Process 10070: 161 nodes malloced for 14 KB
Process 10070: 0 leaks for 0 total leaked bytes.

很明显,分配确实发生了,并且泄漏知道它(+1 个节点,+大约 1 MiB)。如果编译器(clang,Hive Mac 默认设置,没有特殊标志)据说已经优化了它,泄漏如何知道分配?

【讨论】:

    【解决方案2】:

    如果有什么我会冒险打开编译器优化。 在第二个示例中,这可能会忽略该行

    btr = (char*)malloc(4);
    

    在编译期间立即将结果设置为 NULL。

    【讨论】:

    • 允许这样做吗?是不是应该打电话给malloc看它的副作用?
    • 在我上面5.1.2.3p4 上的评论进一步说:“在抽象机器中,所有表达式都按照语义指定的方式进行评估。如果可以推断出表达式的值,实际实现不需要评估表达式的一部分未使用并且产生不需要的副作用(包括任何由调用函数或访问易失性对象引起的)。” (强调我的)。但我想知道是什么标准决定了副作用是否需要
    • gcc 确实优化了对malloc 的调用,并且它似乎完全基于与内置函数名称匹配的函数名称,无论<stdlib.h> 是否为#included与否。
    • 在 gcc 命令行中添加 -fno-builtin 选项会阻止它优化对 malloc 的调用。
    • 嗯。 -fno-builtin 或 -O0 无效,但如果我在 btr = NULL 之后添加 printf("%p",ptr);然后它将显示泄漏。但编译器优化似乎是一个合理的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-20
    • 2010-10-11
    相关资源
    最近更新 更多