解决这个问题,先要知道以下知识:
1. malloc(0)返回结果
ptr = malloc(0);
首先,要知道这个语句有没有问题,最好的方式就是自己跑一下程序;不过答案是,没有语法错误,甚至没有警告!
以下是我查到的关于返回的解答:
malloc() allocates size bytes and returns a pointer to the allocated memory. The memory is not cleared. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().
意思就是:返回值要么是NULL,要么是一个可以被free调用的唯一的指针。
而经过实践,在window和linux上运行后,好像结果返回一个指针,且值大小不为NULL!(仅限于手头上的linux版本和window版本,不针对所有系统);
1.1 如何避免
既然知道了,返回的是一个指针,那么具体返回的什么意思;按理说是一个内存为0的空间?
从个人理解上来说,如果申请一个大小为0的空间,相当于你无法给这个空间进行赋值等操作;而返回一个非NULL指针,仅仅是让你在free的时候,不会产生错误;
官方的意思其实就是这样,为了避免对size的大小进行判断,使size=0的情况也返回一个指针,这样在free的时候就可以做到统一性;
所以,如何避免这个问题呢?其实,如果程序员手动申请内存的话,一般不会出现这个问题;而当size为形参进行申请内存后,size可能就是用户进行设置的,也就是说,在这里可能会导致size=0的情况出现。所以,只要在size>0的时候进行malloc,就可以避免这个问题。
1.2 代码运行结果
所有理论的知识都要进行实践;
所以,我用dev-c++进行测试;编译器版本是TDM-GCC 4.9.2 64-bit release;
int main(int argc, char *argv[]) {
char *p;
p = (char *)malloc(0);
if(p==NULL)
printf("get NULL\n") ;
else
{
printf("get a valib value\n");
printf("addr:%x\n",p);
memcpy(p,"abc",2);
printf("addr:%x is %d,%d\n",p,*p,*(p+1));
free(p);
printf("free success!");
}
}
运行结果如下:
好了,从上面的结果分析出:
- malloc(0)返回的不是NULL;
- 居然能对申请地址0的空间进行操作,并且还能打印!
- 能free成功!
1.2 解析
首先,需要知道,malloc是从堆中使用链表进行申请的。所以申请的空间不单单是数据部分,还有一部分链表的头指针这些空间;
其次,malloc(0)申请到的空间,根据编译器不同,可能分给你的比你要申请的多。也就是说,虽然你申请0空间的内存,但是还是可以进行操作的。
所以,在上面的程序中,对p进行赋值,是可以打印的;
但是,多分配的空间又是多少?
这个,可以自己测试,每个平台申请的应该都不太一样;当使用的超过分配的大小以后,在进行free操作的时候,程序会崩溃;
以我手上的开发板测试情况来看(博通wifi芯片),malloc(0)返回一个有效地址,并且会申请16字节的空间!
可以参考:
https://www.cnblogs.com/xiaowenhu/p/3222709.html
2. malloc(-1)结果是什么?
答案是:不一定
2.1 解析
参考了其他人的博客,发现结果都不一样,有编译失败,有运行死卡死,我这里编译出来时返回NULL。
我这里大致可以看出,此结果和GCC编译器有关系,这里有一个-Walloc-size-larger-than=6
选项和malloc的条件有关系,因此不能确定关系。
不过不用太过纠结,这个一般用于面试刷题用,正经人不会在项目中这么用,除非想作死!
3.杂记
很荣幸今天在面试的时候,面试官看到我这篇博客了,然后问我这个问题。但是由于太久没看这种偏向面试题的东西,大部分都已经忘了,实在很愧疚,自己写的自己居然忘记了。
今天再复习一遍,然后补充一下内容。
其实针对单片机的FreeRTOS来说,申请一个内存,其实有最小单位的,也就是内存管理结构体的大小,也就代表着,一般的malloc(0)和malloc(1)申请的大小是一样的(如果malloc(0)允许的话)
。但是malloc(0)确实不怎么会出现在代码中,所以一般人确实容易忽略这个问题。