我在试着弄清楚如果我试图从"中间"释放一个指针会发生什么. 例如,请查看以下代码:
char *ptr = (char*)malloc(10*sizeof(char));
for (char i=0 ; i<10 ; ++i)
{
ptr[i] = i+10;
}
++ptr;
++ptr;
++ptr;
++ptr;
free(ptr);
我遇到了一个带有未处理异常错误消息的崩溃.
谢谢
我在试着弄清楚如果我试图从"中间"释放一个指针会发生什么. 例如,请查看以下代码:
char *ptr = (char*)malloc(10*sizeof(char));
for (char i=0 ; i<10 ; ++i)
{
ptr[i] = i+10;
}
++ptr;
++ptr;
++ptr;
++ptr;
free(ptr);
我遇到了一个带有未处理异常错误消息的崩溃.
谢谢
当你对一个块进行malloc时,它实际上分配的内存比你要求的要多.这个额外的内存用于存储信息,例如分配的块的大小,到块链中下一个空闲/使用的块的链接,有时还有一些"保护数据",帮助系统检测您是否写入了分配块的末尾.此外,大多数分配器会将内存的总大小和/或起始部分四舍五入到字节的倍数(例如,在64位系统上,它可能会将数据对齐到64位(8字节)的倍数,因为对处理器/总线来说,从未对齐的地址访问数据可能更困难、效率更低),因此,最后可能会出现一些"填充"(未使用的字节).
当您释放指针时,它会使用该地址来查找添加到分配块开头(通常)的特殊信息.如果传入不同的地址,它将访问包含垃圾的内存,因此其行为未定义(但最常见的情况是会导致崩溃)
稍后,如果释放()块,但不要"忘记"指针,将来可能会意外地try 通过该指针访问数据,并且行为未定义.可能出现以下任何情况:
这就是为什么在释放指针指向的内存后确保不使用指针很重要的原因——最好的做法是在释放内存后将指针设置为NULL,因为您可以轻松地测试NULL,并且try 通过NULL指针访问内存将导致错误的但为consistent的行为,这更容易调试.