malloc(0)的运行实验

本文通过实验展示了在VS2017环境下,malloc(0)返回的有效指针并非总是NULL,并可能导致内存越界问题。在Windows Debug x86环境下,分配0字节内存仍能得到内存块,且相邻分配的0字节内存可能是连续的。当对这些内存进行写入操作时,超过48字节会导致堆破坏,引发错误。实验揭示了malloc(0)的不确定性及潜在风险。
摘要由CSDN通过智能技术生成

场景:

碰到这样的题目,问 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)会得到一个正确的指针,也并不是返回一个空指针;对返回的地址写入值,在一定范围内也能正常运行,但是范围大小取决于运行环境。另外,申请的内存可能连续也可能不连续,但这就是另外一个故事了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值