虚拟内存地址空间不足(Borland C++Builder 6程序)
Out of virtual memory address space (Borland C++ Builder 6 program)
我在C++Builder 6下编写的一些应用程序有问题。运行一段时间(周、月)后,应用程序崩溃并关闭,没有任何错误消息。在崩溃前不久的应用程序日志中,我收到了许多"内存不足"的异常。当它抛出内存不足异常时,我查看了这个过程(下面的屏幕截图),它有很多未提交的私有内存空间。这种行为的原因是什么?
几年前,我曾经遇到过这样的问题。原因是链接器选项中未选中"使用动态库"选项。当我查回来时,问题消失了,反之亦然。我制作的测试应用程序只是调用"new char[100000]",然后删除。每次都会释放内存(windows任务管理器中没有出现提交内存),但过了一段时间内存不足,VMMap显示出完全相同的情况。保留了大量私有内存,但大部分未提交。
现在问题又出现了,但我无法用同样的方法解决它。我不知道这是不是原因,但我在同一台机器上测试了Builder 6和2010。现在我只有Builder6,似乎无法像以前那样用测试应用程序重现错误。以太币的方式似乎有一些内存管理器错误或其他什么。CodeGuard没有显示任何内存泄漏。当我用"new"创建内存块时,它会立即显示为"内存提交大小",当删除时,内存使用量会减少,所以我认为内存泄漏不是这样,任务管理器不会显示太多"内存提交尺寸"。
我能做什么吗?有什么办法可以释放未提交的内存吗?如何进一步诊断问题?
屏幕截图:https://i.stack.imgur.com/UKuTZ.jpg
我找到了一种模拟这个问题和解决方案的方法。
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中的一个进行交换。我还没有彻底测试,但它似乎没有任何问题。
我应该把洞项目转移到RAD 2010,但由于一些原因,我被困在了Borland 6。
序言
嗯,有趣的行为。。。我必须补充一些我通过艰苦的努力学到的东西。在尝试了几次后,我立即放弃了BCB6,因为它有太多的错误不符合我的口味(与BCB5相比,尤其是与AnsiString
的处理相比)。所以我在BCB5待了很长一段时间,没有遇到任何问题。我甚至在很大的项目中使用过它,比如CAD/CAM。
几年后,由于我的雇主,我不得不搬到BDS2006,问题开始了(有些可能与你的类似)。除了小的IDE和跟踪/断点/代码保护错误之外,还有更重要的东西,比如:
-
内存管理器
- 如果对同一指针调用两次,
delete/delete[]
将损坏内存管理器,而不会引发任何异常来通知 -
struct
编译器错误的默认构造函数/析构函数是我遇到的最大问题(与delete
结合使用) - 类中错误或丢失的成员函数可能会导致多个
delete
调用!!!由于编译器或C++引擎中的错误
但我很幸运,在这里解决了它:bds 2006 C隐藏内存管理器冲突(class-new/delete[]与AnsiString)
- 如果对同一指针调用两次,
-
错误编译
有时应用程序编译错误,不会引发错误,但exe中缺少一些代码行,和/或与源代码中的顺序不同。我偶尔也会在BCB 5,6中看到这种情况。要解决这个问题:
- 删除所有临时文件,如
~,obj,tds,map,exe,...
- 关闭IDE并再次打开它只是为了确保(有时局部变量(大多数是大数组)的视图会损坏IDE内存)
- 重新编译
- 删除所有临时文件,如
-
小心断点/跟踪/代码保护的行为与原始应用程序不同
尤其是多线程应用程序在跟踪和不跟踪时表现不同。codeguard也有很大的不同(我的意思不是说执行速度减慢会破坏敏感的定时)。例如,codeguard有一个讨厌的习惯,有时会无故抛出内存不足的异常,因此必须反复检查代码的某些部分,直到它通过为止,有时即使内存使用情况仍然相同,而且离内存不足还很远。
-
AnsiString
操作员AnsiString
在VCL法线和分量性质中有两种类型。因此,考虑到这一点是明智的,因为对于组件属性AnsiString
,运算符的操作是不同的。例如,尝试之类的东西Edit1->Text+="xxx";
此外,
AnsiString
运营商仍然存在这样的错误:AnsiString version="aaa"+AnsiString("aaa")+"aaa"; // codeguard: array access violation
-
导入旧的BCB项目
如果可能的话,避免直接导入——它经常会产生一些未知的分配和内存泄漏错误。我不知道为什么,但我怀疑导入的窗口类的处理方式不同,内存泄漏与项目符号#1有关。更好的方法是创建新的应用程序并手动创建/复制组件和代码。我知道这是秘密,但避免问题的唯一安全方法仍然不知道问题在哪里,但简单的*.bdsproj替换无济于事!!!在*.dfm,我没有看到任何可疑的东西。
- Mongodb c++驱动程序:如何查询元素的数组
- C++,系统无法执行指定的程序
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到
- 重载操作程序时出错>>用于类中的字符串 memebr
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 试图在visual studio上用C++创建一个桌面应用程序
- 模板元程序查找相似的连续类型名称
- FFmpeg:制作一个应用程序比直接使用ffmepg更好吗
- 如何通过cpp程序运行shell脚本
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 事件处理程序是Embarcadero C++Builder中的重入程序吗
- c++ Builder XE2或Visual Studio 11,从VB应用程序
- c++ Builder语言 - 没有DragLeave事件处理程序
- 在c++ Builder应用程序中动态加载c# . net程序集
- 无法在C++Builder 2006中编译应用程序清单的资源
- 配置应用程序清单c++ Builder XE3
- 虚拟内存地址空间不足(Borland C++Builder 6程序)
- Delphi与C++Builder之比较——对于做Win32的Java程序员来说,这是更好的选择