#include <iostream>
#include <vector>
#include <ctime>
#include<algorithm>
using namespace std;
namespace _nmsp1
{
//malloc来分配0个字节
void func()
{
char *p = (char*)malloc(0);
if (NULL == p)
printf("got a NULL pointer\n");
else
printf("got a Valid pointer\n");//打印这句话,p有值
*p = '\0'; //正常
strcpy_s(p, 100, "这里是一个测试"); //正常
free(p); //报错
}
}
int main()
{
_nmsp1::func();
return 1;
}
为什么free会报错?
当malloc分配内存时它除了分配我们指定SIZE的内存块,还会分配额外的内存来存储我们的内存块信息,用于维护该内存块。因此,malloc(0)返回一个合法的指针并指向存储内存块信息的额外内存,我们当然可以在该内存上进行读写操作,但是这样做了会破坏该内存块的维护信息,因此当我们调用free(ptr)时就会出现错误。
既然malloc另外分配内存来维护该内存块,也就是说分配来用于维护该内存块的内存的大小也是有限的,那么到底是多少呢?这和可能也依赖于实现,在ubuntu下,是24BYTE
ptr = malloc(0*sizeof(char)) ;ptr是局部指针变量,存储在栈中,它的值是动态分配的一块堆中的空间的首地址所以说这个地址是合法的,但是由于malloc的大小是0,故这个这个地址指向的堆中的存储空间的大小是0,这个指针类似于一个野指针,可以使用的,但是是有风险的,因为不知道这个指针后面的内存空间被谁使用着,要是被核心进程使用,哪肯定会造成相应程序的崩溃2…关于加上free后,程序会崩溃,我理解是由于在堆中并没有对应的空间分配到导致的~
测试代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
int alloc_memory(char *p, int size)
{
printf("\nbefore malloc %p\n", p);
p = (char *)malloc(size);
if (!p)
{
printf("malloc error \n");
return -1;
}
//len of malloc(0)
printf("len of malloc(%d) is %d ,the ture is %d\n", size, strlen(p), malloc_usable_size(p));
//the first member
printf("the first member of malloc(%d) is %p:%d \n", size, p, *p);
//set the first member
*p = 10;
printf("set the first member of malloc(%d) is %p:%d \n", size, p, *p);
//memcpy
memset(p, '\0', 12);
memcpy(p, "01234567890123456789", 12);
printf("after memcpy , the content is %s len is %d , the ture is %d \n", p, strlen(p), malloc_usable_size(p));
free(p);
p = NULL;
printf("\n");
}
int main(int argc, char **argv)
{
int size = -1;
char *p = NULL;
//malloc(0)
size = 0;
alloc_memory(p, size);
printf("---------------------------\n");
//malloc(5)
size = 5;
alloc_memory(p, size);
return 0;
}
从测试结果来看,可以得出以下几个结论:
-
malloc(0)在我的系统里是可以正常返回一个非NULL值的。这个从申请前打印的before malloc (nil)和申请后的地址0x562706602670可以看出来,返回了一个正常的地址。
-
malloc(0)申请的空间到底有多大不是用strlen或者sizeof来看的,而是通过malloc_usable_size这个函数来看的。—当然这个函数并不能完全正确的反映出申请内存的范围。
-
malloc(0)申请的空间长度不是0,在我的系统里它是24,也就是你使用malloc申请内存空间的话,正常情况下系统会返回给你一个至少24B的空间。这个可以从malloc(0)和malloc(5)的返回值都是24看出
-
malloc(0)申请的空间是可以被使用的。这个可以从*p = 10; memcpy(p,“01234567890123456789”,12); 可以得出。但是是有风险的,因为不知道这个指针后面的内存空间被谁使用着,要是被核心进程使用,哪肯定会造成相应程序的崩溃