我有一个非常大的(~1E9)对象数组,我可以在单个线程程序的迭代中使用malloc,realloc和free。
具体地,
//(Individual *ind)
//malloc, old implementation
ind->obj = (double *)malloc(sizeof(double)*acb->in.nobj);
//new implementation
ind->obj = (double *)a_allocate(acb->in.nobj*sizeof(double));
void *a_allocate (int siz){
void *buf;
buf = calloc(1,siz);
acb->totmemMalloc+=siz;
if (buf==NULL){
a_throw2("a_allocate...failed to allocate buf...<%d>",siz);
}
return buf;
}
...
//realloc
ind->obj = (double *)a_realloc(ind->obj, acb->in.nobj*sizeof(double));
void *a_realloc (void *bufIn,int siz)
{
void *buf = bufIn;
if (buf==NULL){
a_throw2("a_realloc called with null bufIn...");
}
buf = realloc(buf,siz);
return buf;
}
...
//deallocate
free(ind->obj);
其他三十个属性的处理方式相似。
但是,每隔几次测试运行,代码就会在仅释放此对象属性(free()语句)时对堆验证失败。在失败时,ind->obj
属性不为null并且具有一些有效值。
我正在做什么有明显的问题?
我对C很新,并不完全确定我是否正确执行了内存操作。
谢谢!
编辑:使用_CRTLDBG_REPORT_FLAG
HEAP[DEMO.exe]: Heap block at 010172B0 modified at 010172E4 past requested size of 2c
答案 0 :(得分:2)
堆验证是延迟指标。可以使用Visual Studio调试堆(调试版本)进行更频繁的检查Microsoft : Debug Heap flags。
替代使用应用程序验证程序并启用堆检查,将有助于找到导致此问题的点。
+-----+----------+-----+ +----+-------------+-----+
| chk | memory |chk2 | | chk| different m | chk2|
+-----+----------+-----+ +----+-------------+-----+
当系统分配内存时,它会在返回指针之前(或之后)放置有关内存的元信息。当这些内存块被覆盖时,会导致堆失败。
这可能是你正在释放的记忆,也可能是直接存在的记忆。
诸如“HEAP [DEMO.exe]:010172B0处的堆块在010172E4处修改过去请求的大小为2c”的消息
意味着01017280处的内存超出了已分配内存的末尾。
这可能是因为malloc
ed / realloc
ed的数量太小,或者循环中出现错误。
+---+-----------------+----+--------------------------+
|chk|d0|d1|d2|d3|d4|d5|chk2| memory |
+---+-----------------+----+--------------------------+
因此,如果您尝试写入上面的d6,那将导致'chk2'被覆盖,这被检测到。在这种情况下,差异很小 - 请求的大小是0x2c,差异= E4 - B0 = 0x34
启用这些调试检查应该会将代码更改为更具崩溃性和可预测性。如果数据中没有随机性,则关闭ASLR(仅用于调试)并且所使用的地址是可预测的,您可以在malloc
/ realloc
中为给定的内存地址设置断点