C内存管理具有更多指向同一位置的指针

时间:2012-11-25 16:13:13

标签: c function pointers memory-management

我正在玩这段代码:

#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'被解除分配,为什么要打印它?函数(int * p)中发生的事情有什么影响,如果main()?(如果可以,解释那个'p'指针发生了什么)

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

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

他们两个都指向同一块记忆,但是当我必须释放它时,我应该在它们两个上免费打电话,还是只打电话给其中一个?(再次解释为什么可能)

4 个答案:

答案 0 :(得分:5)

这是未定义的行为。释放指针只是告诉操作系统可以覆盖分配的内存。由于缺乏更好的词,记忆依旧存在。但是任何事情都可能发生..它现在可能会为你打印,有时它可能是另一个字符或数字,因为另一个程序已写入该存储位置......任何事情都可能发生。

对于你的上一个问题.. a和b只是一个地址的符号名称。在地址上免费拨打电话非常重要,因此无论您是free(a)还是free(b),您都很棒。

答案 1 :(得分:3)

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

答案 2 :(得分:3)

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

但是你永远不应该使用已经释放的内存,因为无法保证内存保持多久。

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

对于@ SSHThis的问题

更新

free(a)仅将内存返回堆中。它不会修改ab。无论是否释放内存,检查if(a)if(b)的计算结果为true。只有当您将ab设置为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 */
}

答案 3 :(得分: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==