循环中的文件读取次数不能超过17次

时间:2011-06-01 14:50:13

标签: c++ malloc

我有一个程序可以读取一组输入文件(每个大约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

任何人都知道会发生什么事情?

提前致谢!

4 个答案:

答案 0 :(得分:2)

好的,这就是它告诉你的事情:在循环中经过17次后,你试图释放一个不再指向malloc块的指针。为什么?因为它发生了17次,我怀疑你有一个数组中的指针,你搞砸了一些索引,或者溢出了一个数组。看看你可能分配了16个任何东西的任何地方。

没有代码,很难提供更多帮助;但是,我认为它在那时崩溃了,所以你可以使用 gdb 找出确切的位置。

现在,这是$ 64K的问题:如果您正在编写C ++,为什么使用malloc并且免费?那么newdelete呢?

答案 1 :(得分:1)

我非常感谢你的帮助! :D最后,我已经解决了这个问题。但我想说我是如何解决它的。

事实证明,数组的所有分配(使用新函数)和解除分配(使用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,即使你确定没有错误的分配/解除分配![/ p>

再次感谢您的帮助!

答案 2 :(得分:0)

我不确定这是否对您有所帮助,但您可以在C ++中读取的文件大小有限制,即2GB。也许这是你的问题的根源:130 * 16 = 2080 MB。我不确定这一点,但值得一试。

答案 3 :(得分:0)

您需要发布一些代码,因为有一些重要的歧义需要解决:

  • 文件阅读
  • 数据分配
  • 内存管理

这些不同的问题可能是您的计划失败的原因。

文件阅读

文件读取有两个方面:文件变量(或文件句柄),a.k.a。std::fstream和数据的目的地。文件或流变量不需要在动态内存中分配,缓冲区或数据变量也不需要。在多次读取文件时,一个好的过程是不为每次迭代分配缓冲区或流。可以在不关闭或删除文件变量的情况下重新定位文件。

数据分配

您的错误源于动态内存分配。更喜欢使用本地定义变量或静态变量来动态分配变量。与JavaC#不同,C ++允许在本地(堆栈)存储区域或自动区域(例如函数或全局变量中的静态变量)中声明变量。减少动态分配的变量数量可以减少内存泄漏,内存碎片或内存不足的可能性。

此外,如果可以,请分配一次变量(在读取文件之前)。创建(分配)变量会产生开销。在循环内创建变量时,开销变得明显。对于大量迭代(大于5或10),请考虑重用在循环外部分配的变量。

内存管理

对程序执行一些内存分配并不错。但是,在多次迭代的情况下,内存分配可能是一场噩梦。最坏的情况是,当一个动态分配的变量被删除(释放,返回到内存池)时,它占用的内存将不再被使用。大多数编译器和操作系统通过设计在可能的情况下组合存储器片段的方法来降低这种可能性。但是,片段可能无法组合,因此您的程序将耗尽{useful}内存。例如,如果您的程序需要64个连续字节,但只有64个字节分散,则分配将失败。

此外,其他语言支持垃圾收集。这是凝结记忆碎片的概念。垃圾收集不附带C ++语言。如果您需要该服务,则必须创建自己的内存池(placement new)并编写自己的G.C。

摘要

我们需要您提供更多信息,例如发生错误的代码片段以及来自编译器或操作系统的确切(逐字)消息。您的原始帖子中没有足够的信息来解决上面列出的一些歧义。