Chinaunix首页 | 论坛 | 博客
  • 博客访问: 530404
  • 博文数量: 87
  • 博客积分: 1549
  • 博客等级: 上尉
  • 技术积分: 970
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-14 16:56
文章分类
文章存档

2013年(10)

2012年(28)

2011年(49)

分类: LINUX

2011-10-24 12:57:08

下面进入正题,关于malloc(0)这个问题,我在网上看到有个面试题好像就是问这个的,原题好像是:
char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
puts("Got a null pointer");
else
puts("Got a valid pointer");
该代码的输出是“Got a valid pointer”,不信的可以尝试下!只给出答案,但没给出具体的原理解答。

下面我说一下关于这个题目的尝试情况:
正常在指针的引用时候,如果定义char *str = NULL;后如果不对其进行malloc的话,执行memcpy(str,"hello",strlen("hello"))是会出现错误的,而且malloc的空间必须要大于等于strlen("hello")。正常的malloc一个大于0的长度,会在堆区分配一段空间来供程序员使用,memcpy等等。理论上来说如果想要赋值一个字符串到目标指针执行的空间,这个指针指向的空间必须有足够的“大小”来存储。按照malloc(a)函数的说明,malloc错误会返回一个NULL指针,如果执行成功会返回一个大小为a的空间,malloc(0)如果可以成功执行,则应该在堆区分配一个大小为0的空间,但我尝试往这个空间赋值,会发现无论你要复制的字符串有多长都可以复制进去,和正常的malloc(strlne(str))这样不同的是这个空间无法通过free来释放掉,free(str)就会报错。

 

解答:

首先来解释malloc(0)的问题,这个语法是对的,而且确实也分配了内存,但是内存空间是0,就是说返回给你的指针是不能用的,感觉奇怪吧?但是从操作系统的原理来解释就不奇怪了,这要涉及操作系统维护内存的方法来说了,在内存管理中,内存被分为2部分,栈和堆,栈有自己的机器指令,是一个先进后出的数据结构,我就在这里不再过多解释了,malloc分配的内存是堆内存,由于堆没有自己的机器指令,所以要有系统自己编写算法来管理这片内存,通常的做法是用链表,在每片被分配的内存前加个表头,里面存储了被分配内存的起始地址和大小,你的malloc返回的就是表头里的起始指针,这个地址是由一系列的算法得来了,通常不会为0,一旦分配成功,就返回一个有效的指针,对于分配0空间来说,算法已经算出可用内存的起始地址,但是你占用0空间,所以对那个指针操作就是错误的,操作系统一般不知道其终止地址,因为有占用大小就可以推出终止地址,还有就是即使分配0空间也要释放它,其实是释放的链表结点

还有,返回的指针是可用地址的起始地址,虽然你可以无限赋值,但是其实是错误的,因为可能有其他有用的数据在那一片区域,如果指针越界就会出现意想不到的事情。

阅读(1339) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~