char *a = (char*)malloc(3 * sizeof(char));
strcpy(a, "123");
free(a);
以上代码会报错,如果加断点调试的话会发现报错点是在free(a)上。
具体原因是忘记了字符串末尾的’\0’结束字符,所以这段内存申请是存在申请不足的问题,从而使得使用时出现了堆越界问题。
我们先想为什么 free()函数为什么不需要指定内存大小就能对动态申请的内存块执行释放操作。这其实就暗含着问题的来源,事实上,malloc在动态申请内存的时候并不是仅仅截取了用户指定大小的一块内存给用户使用,在申请得到的这块内存的前后若干字节里都存着有关这块内存的信息,其中做主要的就是这块内存的大小,在free时候,函数自动查找这个数值进行释放。其中,若malloc返回得到的是int型的内存块时,这块内存的大小的数值存在距离内存块头指针前面0x10的一个int型内存块中,(即,若内存块头指针是0x001c50,申请了10个字节,那么在0x001c40开始的4个字节里的数值刚好是0x28(16进制数))。参考:https://www.cnblogs.com/xxNote/p/4009359.html
所以基于以上实验可想而知如果一旦内存越界,会造成该内存块相关信息遭到破坏,导致free出错。
可以通过如下方法在内存不足时对动态分配的内存进行再分配
char *a = (char*)malloc(3*sizeof(char));
cout << "eat memory!" << endl;
int num = 5;
if (!a)
{
a = (char*)realloc(a, (num + strlen(a))*sizeof(char));
}