场景:
碰到这样的题目,问 malloc(0) 有什么后果和输出,这里来VS上进行运行试验
问题描述:
我们在堆上申请一块内存,若申请size为0,有很多文章已经进行了描述:参考1,参考2,参考3,参考4
这里使用VS2017运行效果与参考文章不太一致,过程如下:
char *ptr,*next;
char *tmp1, *tmp2, *tmp3;
//申请多个size为0的内存
tmp1 = (char*)malloc(0 * sizeof(char));
tmp2 = (char*)malloc(0 * sizeof(char));
tmp3 = (char*)malloc(0 * sizeof(char));
ptr = (char*)malloc(0 * sizeof(char));
//申请一个大小为2的内存并写入字符串 “s”
next = (char*)malloc(2 * sizeof(char));
next[0] = 's';
next[1] = '\0';
cout << next << endl;
//判断size为0的内存是否有效
if (NULL == ptr)
printf("got a NULL pointer\n");
else
{
printf("got a Valid pointer\n");
strcpy_s(ptr, 2, "a");
cout << ptr << endl;
cout << next << endl;
// free(ptr);
}
运行效果如下:
可见:申请size为0的内存可以返回有效地址,并且除第一个申请的内存地址较远(0x00405ab0),后面申请的均为连续区域,每个相差0x30(48B)。
另外,可以推测在此环境下(windows,VS2017,debugx86),若申请内存小于48B,则均为48B。这篇文章解释了为什么是48B。
进行一个内存写入越界试验,进行如下修改:
//将长度为50,包含49个'a'与1个'\0'的字符串,拷贝到ptr所指的内存
strcpy_s(ptr, 50, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
运行结果如下:
可见:内存写入越界,对 ptr 指针的写入,导致了next指针所指内容发送的变化,并且程序报错:触发了一个断点
原因是堆已被破坏。
减少写入个数,当降至长度为47时,写入没毛病,不会出错:
strcpy_s(ptr, 47, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
即,写入48B以下的空间,并不会出错;等于48B或者大于48B的空间,会破坏堆,这一点参考文章有讲。
最后:
malloc(0)会得到一个正确的指针,也并不是返回一个空指针;对返回的地址写入值,在一定范围内也能正常运行,但是范围大小取决于运行环境。另外,申请的内存可能连续也可能不连续,但这就是另外一个故事了。