malloc与free的疑惑

int main()
{
  char *str = (char*) malloc(3 * sizeof(char));
  char *index = str;
  long long count = 0;

  while(index != NULL){
    printf("%p\n", index++);
    count ++;
  }

  printf("lld\n", count);
}

在上面的代码中,我用malloc分配了3个字节的空闲内存。理论上(index+4)应该等于NULL,此时就应该停止循环,但是上面的代码会在while中不断的循环输出地址。
起初,我认为这应该是malloc只是给出一块内存空闲空间的首地址,并未限制空间的大小。而是由free函数根据malloc的参数来做回收,所以又试了下面的例子:

int main()
{
  char *str = (char*) malloc(5 * sizeof(char));
  char *index = str;

  for(int i = 0; i < 10; i++){
    *(index+i) = 'a';
  }
  //输出字符的ASCII码
  for(int i = 0; i < 10; i++){
      printf("%d ", *(str+i));
  }
  printf("\n");

  free((void*) str);

  //输出字符的ASCII码
  for(int i = 0; i < 10; i++){
    printf("%d ", *(str+i));
  }
}

实际的输出结果是这样的:

97 97 97 97 97 97 97 97 97 97
0  0  0  0  97 97 97 97 97 97

无论怎样修改malloc中分配的字节数,总是前面的4个97变为0。
为什么会出现这样奇怪的结果?请大家帮我解释一下这个问题,感激不尽!!!

阅读 5.6k
5 个回答
  1. malloc不会在分配的内存的下一个字节补上NULL,它也不会初始化内存为NULL,它只是在堆上开辟一块空间。
  2. free会回收已分配的内存,它只是把一段内存重新标记为可用。但是str的值还是没变的,那么它指向的区域将是“invalid”的,也即是什么值都有可能。可能你的程序刚好只重新使用了前四位,所以后面几位还是保持原来的值不变。

首先,malloc只负责分配空间,但不会对空间进行初始化;其次,index变量保存的是一个地址,你可以想象为一个64位整数,你一直index++,为啥会期望index+4就是NULL呢;最后,即使使用(*index) != NULL也是错的,因为你是在地址偏移量0 ~ N-1上分配了空间,并不能保证偏移量为N的位置的内容就是NULL啊,所以第一段代码的用法是错的。

malloc只是给出一段空间的首地址不假,但是:
1. 它不会为你初始化这段内存中的任何值
2. 它只保证从你申请到的地址开始知道你所申请的长度的偏移之间的空间给你安全使用

所以:
将任何内存位置上的值以数值类型打印出来,和它本身是不是被某个user使用根本没有关系,如果malloc或者其他内存分配函数都能带有问题中所设想的NULL区域,大量的软件bug就会早早暴露出来了。

我的习惯是 malloc之后立即memset
或者使用calloc替代malloc

你是不是受字符串的自动\0作为结束影响的?

1.malloc和字符串没有任何关系,它只是分配出你指定大小的空间让你使用而已,至于这段空间之外的其他空间数据怎么样你是完全不可预测的。
2、而free回收的空间也正是你mallco的那段空间,回收之后你就没有对该空间的访问权限了(你对它的访问是不可预测的),所以free之后再去测试那段空间上有什么数据也是没有意义的。

当然,作为研究,所有的尝试都是有意义的,但,去看malloc和free的源代码可能更有意义。

顺便提一下,free里面的str不用显示的转换成void *,指针类型都是可以自动转成void *的。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进