我有一个程序,它读取一组输入文件(每个大约130MB)并执行一些数据搜索。程序必须多次读取所有输入文件。通过循环执行读取。在循环到达第17次迭代之前,一切都很好。然后出现以下消息(vvfield是主程序的名称):
vvfield(13053) malloc: *** error for object 0x100100301: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap
循环执行次数可以少于17次,并且运行良好,但是如果循环执行次数超过17次,则会出现消息。主要关注的是该程序应该执行200多次循环
我不知道一个文件的读取次数是否有限制。
输入文件在一个独立的函数中打开、关闭和清除,每个输入文件都是从开始到某个点读取的(该点是可变的,但有时可能是文件的末尾)。
我正在使用g++进行编译,并在Mac OS Snow Leopard 10.6.7 上工作
有人知道会发生什么吗?
提前感谢!
好吧,它告诉你:在循环17次之后,你试图释放一个不再指向malloc块的指针。为什么?由于这种情况发生了17次,我怀疑你在一个数组中有指针,你把一些索引搞砸了,或者溢出了一个数组。看看你可能分配了16个地方。
如果没有代码,很难提供更多帮助;然而,我认为它在这一点上崩溃了,所以你可以使用gdb来找出确切的位置。
现在,这里有一个6400美元的问题:如果你在写C++,为什么要使用malloc
和免费?new
和delete
呢?
我真的很感谢您的帮助!:D终于,我解决了这个问题。但我想说我是如何解决的。
事实证明,数组的所有分配(使用new函数)和释放(使用delete[]函数)本身都没有错误,而是一种"天真"的错误。
显然,如果不查询指针的状态,g++编译器将无法正常工作。例如,我更改的功能如下:
void clearSingleBinVars(real** &mean,real** &sd,int** &npart)
{
extern int maxNoFrames;
for (int i=0; i<maxNoFrames; i++) {
delete[] mean[i];
delete[] sd[i];
delete[] npart[i];
}
delete[] mean; mean=NULL;
delete[] sd; sd=NULL;
delete[] npart; npart=NULL;
}
我添加了一些代码,新功能是:
void clearSingleBinVars(real** &mean,real** &sd,int** &npart)
{
extern int maxNoFrames;
/*Added code: next four lines*/
if ((mean==NULL)||(sd==NULL)||(npart==NULL)) {
cout << "Warning: attempting to deallocate null arrays!n";
return;
}
for (int i=0; i<maxNoFrames; i++) {
delete[] mean[i]; mean[i]=NULL;//added mean[i]=NULL;
delete[] sd[i]; sd[i]=NULL;//added sd[i]=NULL;
delete[] npart[i]; npart[i]=NULL;//added npart[i]=NULL;
}
delete[] mean; mean=NULL;
delete[] sd; sd=NULL;
delete[] npart; npart=NULL;
}
有了这些变化,一切都很好!
真正令人印象深刻的是,我没有收到任何警告消息,即当程序运行时,没有错误的分配/释放。。。我只是添加了警告信息并解决了问题。
我认为这是一个编译器的东西。因此,建议是,每当您重复分配/解除分配对象时,始终检查指针,并在解除分配时始终将其设置为NULL,即使您确信没有错误的分配/解除配置!
再次感谢您的帮助!
我不确定这是否对您有帮助,但您可以在C++中读取的文件大小有限制,即2GB。也许这就是问题的根源:130*16=2080 MB。我对此不确定,但值得检查一下。
您需要发布一些代码,因为有一些重要的歧义需要解决:
- 文件读取
- 数据分配
- 内存管理
这些不同的问题可能是导致程序失败的原因。
文件读取
文件读取有两个方面:文件变量(或文件句柄),也称为std::fstream
,以及数据的目的地。文件或流变量不需要在动态内存中分配,缓冲区或数据变量也不需要。当多次读取文件时,一个好的过程是不为每次迭代分配缓冲区或流。可以在不关闭或删除文件变量的情况下重新定位文件。
数据分配
您的错误源于动态内存分配。更喜欢使用局部定义变量,或者使用静态变量来动态分配变量。与Java
或C#
不同,C++允许在本地(堆栈)存储区域或自动区域中声明变量(如函数中的静态变量或全局变量)。减少动态分配的变量数量可以减少内存泄漏、内存碎片或内存不足的可能性。
此外,如果可以的话,分配变量一次(在读取文件之前)。创建(分配)变量会产生开销。在循环中创建变量时,开销会变得明显。对于大量迭代(5或10次以上),考虑重新使用循环外分配的变量。
内存管理
执行一些内存分配对程序来说并不坏。然而,在多次迭代的情况下,内存分配可能是一场噩梦。最坏的情况是,当动态分配的变量被删除(释放,返回到内存池)时,它所占用的内存将不再使用。大多数编译器和操作系统都通过设计在可能的情况下组合内存片段的方法来降低这种可能性。然而,有一种可能性是片段无法组合,因此您的程序将耗尽{可用}内存。例如,如果您的程序需要64个连续的字节,但周围只有64个字节,则分配将失败。
此外,其他语言也支持垃圾回收。这就是凝聚记忆片段的概念。C++语言没有垃圾回收。如果你想要这项服务,你必须创建自己的内存池(placement new
),并编写自己的G.C.
摘要
我们需要您提供更多信息,例如发生错误的代码片段以及来自编译器或操作系统的确切(逐字)消息。你的原始帖子没有包含足够的信息来解决上面列出的一些歧义。