【问题标题】:memory corruption内存损坏
【发布时间】:2009-12-21 06:17:21
【问题描述】:

我正在运行一个小型 c 程序:

#include<stdio.h>
int main()
{
char *p;
p = (char *)malloc(10);
free(p);
free(p);
free(p);
printf("\npointer is freed!!\n");
}

基本上我正在释放已经被释放的内存。 我认为应该导致核心转储!不是这样吗?

但它正在打印

pointer is freed!!

我错在哪里?

【问题讨论】:

    标签: c memory-leaks coredump


    【解决方案1】:

    根据手册页,“如果之前已经调用过 free(ptr),则会发生未定义的行为。”

    它不需要炸毁; “不做任何事情”是完全可以接受的未定义行为。还有鼻魔。不要依赖它。

    【讨论】:

    • 防止这种情况发生的一个好方法是free(ptr); ptr = NULL;,因为free(NULL); 是无操作的。此外,在 OP 的示例中,malloc 可能已经返回 NULL
    【解决方案2】:

    您的程序存在多个问题:

    1. 由于您使用的是malloc()free(),因此您应该在调用任何这些函数之前执行#include &lt;stdlib.h&gt;
    2. 不需要从malloc() 转换返回值:它返回一个void *,它可以安全地分配给任何其他指针类型(函数指针除外)。所以,你可以这样做:p = malloc(10);
    3. 一旦释放由malloc()realloc() 分配的指针,以任何方式使用指针值都是不好的:尤其是,您不能再次调用free()
    4. int main() 最好写成int main(void)
    5. 由于main() 返回int,您应该从中返回一个值。传统上,0 表示成功。

    当然,程序的主要(不是双关语)问题是多次释放它,但上面提到的其他问题也很重要。一旦你成功地 free()'d 指针,调用 free() 是未定义的行为:程序可以做任何事情,包括(不幸的是),似乎没有做任何坏事。我说“不幸”是因为它可能会给你一种安全感,可以多次free() 一个指针。

    【讨论】:

    • 一个从不抱怨双重释放的 free() 与一个总是分配第一个空闲块的 malloc() 是灾难的完美秘诀。
    • @jbcreix:这是实施质量问题。在某些系统上,可能不希望对双重释放等进行额外检查。在其他系统/用途上,这种检查非常有意义。
    • ad 3:这就是 OP 的奇妙之处:他以一种糟糕的方式使用它,但没有发生任何不好的事情。广告4:我不同意。 main() 通常有参数;如果你不使用它们,()(void) 更好。
    • @glglgl:问题被标记为c,这意味着适用C规则。所以,() 并不比(void) 好。例如,请参阅securecoding.cert.org/confluence/display/seccode/…
    【解决方案3】:

    只是为了添加其他答案,我想指出,如果您将指针设置为 NULL,然后调用 free(),则该行为将不再是未定义的。这几乎是无操作的。但是,如果指针被释放并且您在将指针分配给不同的位置(甚至是 NULL)之前再次调用 free(),您无法确定会发生什么。这可能会导致某些实现出现核心转储,而其他实现则不会发生任何事情。

    【讨论】:

      【解决方案4】:

      释放已经释放的内存,导致未定义的行为,你很幸运,在这种情况下,在其他时候你可能会得到你的核心转储

      【讨论】:

        【解决方案5】:

        这取决于实现此功能的操作系统(linux、windows...)的实现。它们的行为可能因操作系统而异(未定义的行为),因此您不能依赖它们,并且您必须只释放一次程序中所有分配的内存。

        编辑:它不是操作系统的一部分,而是标准库的一部分,取决于操作系统。

        【讨论】:

          【解决方案6】:

          我希望大多数编译器的 DEBUG 版本能够检测到这种类型的故障并准确报告发生的情况。 MSVC 也会这样做。

          在 RELEASE 中,可以对其进行优化以更快地生成不可预测的行为。

          【讨论】:

            【解决方案7】:

            堆损坏不需要立即引起问题。释放的内存(或部分内存)用于分配其他结构可能会发生这种情况,然后可能会导致问题。 freeing memory 不止一次总是 UB(未定义),即使您当时没有看到不良影响也不应该这样做。

            【讨论】:

            • 我相信这个问题与堆损坏无关,因为原始发布者不会再次尝试使用指针。相反,他们询问是否在同一个指针上多次调用 free。
            • 调用多个 free 会导致堆损坏。我相信它仍然回答了 OP 的问题。此外,它不必是相同的指针,而是相同的内存,可以重复使用并可能导致损坏。
            • 在同一个上多次调用 free 可能导致堆损坏。
            猜你喜欢
            • 2015-06-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-04-04
            • 2012-06-13
            • 1970-01-01
            相关资源
            最近更新 更多