出于虚拟内存地址空间(Borland C ++ Builder 6程序)

我有一些在C ++ Builder 6下编写的应用程序的问题。经过一段时间的运行(一周,一个月),应用程序崩溃并closures,没有任何错误消息。 在我的应用程序日志崩溃前不久,我得到了许多“内存不足”的例外。 我查看了抛出内存exception的过程(下面的截图),它有很多未提交的私有内存空间。 什么可能是这种行为的原因?

几年前,我曾经有过这样的问题。 原因是在链接器选项中未选中“使用dynamic库”选项。 当我检查后,问题消失,反之亦然。 我所做的testing应用程序只是调用“新字符[1000000]”,然后删除。 每次释放内存(在Windows任务pipe理器中没有提交的内存上升),但是一段时间后,内存不足,VMMap显示了完全相同的结果。 很多保留的私人内存,但大部分都没有提交。

现在的问题返回,但我不能以同样的方式解决它。 我不知道是不是这个原因,但是我把Builder 6和2010安装在同一台机器上。 现在我只有Builder 6,看起来我不能像以前那样用testing应用程序重现错误。 以太的方式似乎有一些内存pipe理器错误什么的。 CodeGuard不显示任何内存泄漏。 当我用“new”创build内存块时,它立即显示在“内存提交大小”中,当删除内存使用量减less时,所以我假设内存泄漏不是这种情况,任务pipe理器不会显示太多的“内存提交大小” 。

有什么我可以做的吗? 有没有什么办法可以释放未提交的内存? 如何进一步诊断问题?

截图: http : //i.stack.imgur.com/UKuTZ.jpg

Solutions Collecting From Web of "出于虚拟内存地址空间(Borland C ++ Builder 6程序)"

我找到了一种方法来模拟这个问题和解决方案。

for(int i=0; i<100; i++) { char * b = new char[100000000]; new char; delete b; } 

Borland的内存管理器保留了一块大小为4kB的页面的倍数的内存块。 当分配不同于4kB倍数的内存大小时,borland可能会使用一些空闲空间来分配其他内存块。 当第一个块被释放时,第二个块仍然保留着空闲内存块。

首先看代码应该只会导致100B的内存泄漏,但事实上它会在少于16次的迭代之后导致内存分配异常。

我发现了这个问题的两个解决方案 。 一个是FastMM,它的工作,但也带来一些麻烦。 第二种解决方案是将borlndmm.dll与Embarcadero Rad Studio 2010中的borlndmm.dll进行交换。我没有完全测试它,但似乎没有任何问题。

我应该把这个漏洞项目移到RAD 2010,但由于某些原因,我被困在了Borland 6。

序幕

嗯,有趣的行为…我必须补充一些我学到的东西。 我尝试了几次之后立即解散了BCB6 ,因为它有太多的错误 (与BCB5相比,尤其是AnsiString的处理)。 所以我和BCB5呆了很长时间没有任何问题。 我甚至用它来做CAD / CAM等非常大的项目。

经过几年的传递,我不得不因为我的老板和问题的开始而转移到BDS2006有些可能和你的相似 )。 除了小的IDE和trace / breakpoint / codeguard错误外,还有更重要的东西,比如:

  1. 内存管理器

    • delete/delete[]损坏内存管理器如果调用两次相同的指针, 而不会引发任何异常通知…
    • 错误的默认构造函数/析构函数 struct编译器错误是我最大的问题(与delete结合)
    • 在类中的成员函数错误或缺少可能导致多个delete调用! 无论是在编译器还是在C ++引擎中。

    但我很幸运,并在这里解决: BDS 2006 C隐藏内存管理器冲突(类新/删除[]与AnsiString)

  2. 编译错误

    有时应用程序编译错误,没有错误引发,但一些代码行在exe中丢失和/或在源代码中的顺序不同。 我偶尔也在BCB 5,6看到这个。 要解决这个问题:

    1. 删除所有临时文件,如~,obj,tds,map,exe,...
    2. 关闭IDE,并再次打开它,以确保(有时查看本地变量(主要是大数组)损坏的IDE内存)
    3. 再次编译
  3. 当心断点/跟踪/ codeguard行为不同,然后原始的应用程序

    特别是对于多线程应用程序行为不同而跟踪,而不是。 另外Codeguard也有很大的不同(我并不是说执行的速度慢了,这会破坏敏感的时机)。 例如, codeguard有一个恶意的习惯,抛出内存异常没有理由,所以有时候代码的某些部分必须一遍又一遍地检查,直到有时候,即使mem的使用仍然是相同的, 远离 mem。

  4. AnsiString运算符

    VCL中有两种类型的AnsiString ,normal和component属性。 所以考虑到这一点是明智的,因为对于组件属性AnsiString的操作是不同的。 尝试例如类似的东西

     Edit1->Text+="xxx"; 

    还有像这样的AnsiString运算符错误:

     AnsiString version="aaa"+AnsiString("aaa")+"aaa"; // codeguard: array access violation 
  5. 导入旧的BCB项目

    如果可能,避免直接导入,通常会造成一些未知的分配和memleaks错误。 我不知道为什么,但我怀疑,导入的窗口类处理不同,memleaks与子弹#1有关 。 更好的方法是创建新的应用程序并手动创建/复制组件和代码。 我知道这是后退,但唯一安全的方法来避免问题仍然不知道问题出在哪里,但简单* .bdsproj替换将不会帮助! 在* .dfm中,我没有看到任何可疑的东西。