2

我正在玩这段代码:

#include <stdlib.h>
#include <stdio.h>

void function(int *p){
    free(p);
}

int main(){
    int *i = calloc(3, sizeof(int));
    function(i);
    i[0] = 'a';
    printf("%c\n", i[0]);
    return 0;
}

我希望得到一个错误,但它打印了'a',如果'a'被释放,为什么它会打印它?如果 main(),函数(int *p)中发生的事情有什么影响?(如果可以,请解释那个“p”指针发生了什么)

假设我在同一个函数中有这两个:

int *a = malloc(...);
int *b = a;

它们都指向同一块内存,但是当我必须释放它时,我应该对它们都调用 free 还是只调用其中一个?(如果可能,再次解释原因)

4

4 回答 4

5

那是未定义的行为。释放指针只是告诉操作系统分配的内存可以被覆盖。记忆还在那里……因为没有更好的词了。但是任何事情都可能发生......它现在可能会为您打印一个,有时它可能是另一个字符或数字,因为另一个程序已写入该内存位置......任何事情都可能发生。

对于您的最后一个问题.. a 和 b 只是地址的符号名称。在地址上免费拨打电话很重要,所以无论您是否这样做free(a)free(b)您都是伟大的。

于 2012-11-25T16:14:56.757 回答
3

它打印'a'因为你很幸运。这是未定义的行为。它当前“取消分配”,这意味着它(内存位置)被标记为“覆盖”

于 2012-11-25T16:16:07.877 回答
3

您已将内存返回到堆中,但尚未重用内存。因此,有时内存内容保持不变,您可以读取和写入它,就好像它仍在使用中一样。

但是你永远不应该使用已经释放的内存,因为不能保证内存保持这种状态多久。

在您的第二部分a = malloc(...); b = a中,两个变量都指向相同的内存。由于这只是一个字节,因此您必须free()恰好一次。否则你有一个双重释放,这可能会破坏堆。

@SSH更新这是问题:

free(a)只将内存返回到堆中。它不修改ab。检查if(a)if(b)评估为真,内存是否被释放。只有当您设置aorb为 null 时,检查才会评估为 false,无论内存是否被释放。

所以free(a)if(a)是独立的操作。他们不互相影响。

a = malloc(10); /* assuming malloc doesn't return NULL */
if (a) {
    /* will be true, memory is NOT freed */
}

free(a);
if (a) {
    /* will be true, although memory is freed */
}

a = malloc(10); /* assuming malloc doesn't return NULL */
a = NULL;
if (a) {
    /* will NOT be true, although memory is NOT freed */
}
于 2012-11-25T16:17:00.770 回答
2

您的代码是错误的,但出现错误意味着某些东西正在检查它是否错误。C 中有很多你可以做的事情是错误的,但从未被检查过。这样做通常是因为进行检查会降低性能,或者检查起来非常困难。访问已释放的内存就是其中之一。通过 valgrind 之类的工具运行程序会报告更多此类问题,但程序运行速度会慢得多。

这是 valgrind 的输出:

==19080== Invalid write of size 4
==19080==    at 0x8048468: main (main.c:11)
==19080==  Address 0x403b028 is 0 bytes inside a block of size 12 free'd
==19080==    at 0x4006EED: free (vg_replace_malloc.c:366)
==19080==    by 0x8048434: function (main.c:5)
==19080==    by 0x8048463: main (main.c:10)
==19080== 
==19080== Invalid read of size 4
==19080==    at 0x8048472: main (main.c:12)
==19080==  Address 0x403b028 is 0 bytes inside a block of size 12 free'd
==19080==    at 0x4006EED: free (vg_replace_malloc.c:366)
==19080==    by 0x8048434: function (main.c:5)
==19080==    by 0x8048463: main (main.c:10)
==19080== 
于 2012-11-25T16:20:46.463 回答