我正在使用VS08来构建/运行以下c ++代码:
#include <stdlib.h>
struct Header
{
int count;
}*lstHeader=NULL;
int main()
{
for(int i=0;i<10;i++)
{
lstHeader=(Header*)realloc(lstHeader,sizeof(Header)+i);
lstHeader[i].count=i;
}
return 1;
}
Run Code Online (Sandbox Code Playgroud)
并在运行后我得到以下VS异常:
Windows has triggered a breakpoint in MyProgram.exe.
This may be due to a corruption of the heap, which indicates a bug in
MyProgram.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while MyProgram.exe has focus.
The output window may have more diagnostic information.
Run Code Online (Sandbox Code Playgroud)
我试过malloc lstHeader而不是将它分配给NULL,但是同样的VS异常发生了,我无法想象y.
你需要考虑i到达1 时会发生什么.让我们假设一个四字节整数.
在i == 0,您为一个Header加上额外的零字节分配足够的字节.然后设置Header[0].count为0.那里没有问题,你只更改了你分配的四个字节.
在i == 1,您为一个Header加上一个额外的一个字节(总共五个字节)分配足够的字节.然后设置Header[1].count为1.这会更改内存块的字节4,5,6和7(从零开始),尽管您只有0到4的字节可供使用.换句话说,该操作需要额外的四个字节而不是您要求的一个额外字节.
以图形方式查看:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | |1|1|1|1|1|1|1|1|1|1|2|2|2|2|
offset: |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
i=0, get: <------->
use: <------->
i=1, get: <--------->
use: <--------------->
i=2, get: <----------->
use: <----------------------->
i=3, get: <------------->
use: <------------------------------->
i=4, get: <--------------->
use: <--------------------------------------->
i=5, get: <----------------->
use: <----------------------------------------------->
Run Code Online (Sandbox Code Playgroud)
如您所见,每次迭代都会为您提供额外的字节,但您需要额外的四个字节.现在这实际上可能会工作一段时间,因为大多数malloc调用会给你一个最小分辨率,如16个字节(要求1,2,3或16,你得到16,要求20或30,你得到32).但它仍然是未定义的行为,你不应该依赖它.
而且,无论如何,你最终会达到不再有用的程度.这一点是sizeof*(i+1)你所需要的,超过16字节的阈值,而sizeof+i你要求的保持低于它.然后你会写出超出你分配的内存(即使使用填充),你也会在内存领域发挥作用.
你应该拥有的是:
lstHeader = realloc (lstHeader, sizeof(Header) * (i+1));
Run Code Online (Sandbox Code Playgroud)
这将确保您有足够的空间容纳Header内存分配中所需的元素.这i+1是因为初始分配必须有一个元素,即使它i是零.