【问题标题】:C memory management with more pointers to the same location具有更多指向同一位置的指针的 C 内存管理
【发布时间】:2012-11-25 16:13:13
【问题描述】:

我在玩这个代码:

#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 还是只调用其中一个?(如果可能,再次解释原因)

【问题讨论】:

    标签: c function pointers memory-management


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      更新 @SSHThis's question:

      free(a) 只将内存返回到堆中。它不会修改ab。检查if(a)if(b) 评估为真,内存是否被释放。只有当您将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 */
      }
      

      【讨论】:

      • 感谢您的明确回答,这对我来说更有意义。我有一个挥之不去的问题,可能不值得提出一个全新的问题。使用您示例中的变量名,如果b 可能等于ab 也可能等于一些新分配的内存,我可以free(a) 然后进行if(b) free(b) 之类的检查吗?我假设如果前者为真,a 将被释放,因此if(b) 不会评估为真?
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        您的代码是错误的,但出现错误意味着某些东西正在检查它是否错误。 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== 
        

        【讨论】:

          猜你喜欢
          • 2015-05-19
          • 1970-01-01
          • 1970-01-01
          • 2021-11-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-23
          • 1970-01-01
          相关资源
          最近更新 更多