我正在使用 BDS 2006 Turbo C ++ 很长一段时间,我的一些大项目( CAD / CAM,3D gfx引擎和Astronomic计算)偶尔抛出一个例外(例如,在24/7重负荷使用的3-12个月中一次)。经过大量调试后我发现了这个:
//code1:
struct _s { int i; } // any struct
_s *s=new _s[1024]; // dynamic allocation
delete[] s; // free up memory
此代码通常位于模板中,其中_s
也可以是类delete[]
此代码应该正常工作,但delete[]
对结构不起作用(类看起来没问题)。没有异常被抛出,内存被释放,但它以某种方式损坏了内存管理器分配表,在此之后任何新的分配都可能是错误的(新的可以创建具有已分配空间的重叠分配,甚至是未分配的空间,因此偶尔会出现异常)
我发现如果我将空的析构函数添加到_s
,而不是突然看起来一切正常
struct _s { int i; ~_s(){}; }
现在好了,奇怪的部分。在我将此更新到我的项目后,我发现AnsiString
类也有错误的重新分配。例如:
//code2:
int i;
_s *dat=new _s[1024];
AnsiString txt="";
// setting of dat
for (i=0;i<1024;i++) txt+="bla bla bla\r\n";
// usage of dat
delete[] dat;
在此代码dat
中包含一些有用的数据,之后是通过添加行创建的txt
字符串,因此必须重新分配txt
几次,有时dat
数据被txt
覆盖(即使它们没有重叠,我重新分配AnsiString
所需的临时txt
与dat
重叠
所以我的问题是:
有没有办法避免AnsiString
(重新)分配错误? (但仍在使用它)
AnsiString
不会导致问题。它们仅在使用时发生。真正的问题可能是在 OpenGL 客户端之间切换。我有打开/保存对话框,带有矢量图形预览。如果我为这些 VCL 子窗口禁用 OpenGL ,则AnsiString
内存管理错误将完全消失。我不支持问题是什么( MFC / VCL 窗口之间不兼容,或者更可能是我在切换上下文时犯了一些错误,将进一步调查)。关注 OpenGL 窗口是:Canvas
客户区内Canvas
客户区P.S。
new/delete/delete[]
次使用的数量,而不是分配的尺寸AnsiString
和模板与内部动态分配,但可能它们也在更简单的项目中但很少发生我想念它。抱歉英语/语法不好...... 任何帮助/结论/建议表示赞赏。
答案 0 :(得分:2)
经过大量调试后,我很好地隔离了这个问题。 在尝试为已删除的指针调用任何删除后,bds2006 Turbo C ++的内存管理已损坏。例如:
BYTE *dat=new BYTE[10],*tmp=dat;
delete[] dat;
delete[] tmp;
此后内存管理不可靠。 ('new'可以分配已经分配的空间)
当然删除相同的指针两次是程序员方面的错误,但我发现产生这个问题的所有问题的真正原因(源代码中没有任何明显的错误)看到这段代码:
//---------------------------------------------------------------------------
class test
{
public:
int siz;
BYTE *dat;
test()
{
siz=10;
dat=new BYTE[siz];
}
~test()
{
delete[] dat; // <- add breakpoint here
siz=0;
dat=NULL;
}
test& operator = (const test& x)
{
int i;
for (i=0;i<siz;i++) if (i<x.siz) dat[i]=x.dat[i];
for ( ;i<siz;i++) dat[i]=0;
return *this;
}
};
//---------------------------------------------------------------------------
test get()
{
test a;
return a; // here call a.~test();
} // here second call a.~test();
//---------------------------------------------------------------------------
void main()
{
get();
}
//---------------------------------------------------------------------------
在函数get()
中,类a的析构函数被称为两次。一次为真正的a和一次为它的副本,因为我忘了创建构造函数
test::test(test &x);
[Edit1]进一步升级代码
好的我已经改进了类和struct甚至模板的初始化代码,以修复更多的bug案例。将此代码添加到任何结构/类/模板,如果需要,添加功能
T() {}
T(T& a) { *this=a; }
~T() {}
T* operator = (const T *a) { *this=*a; return this; }
//T* operator = (const T &a) { ...copy... return this; }
T
是结构/类名称T
内部使用动态分配时才需要最后一个运算符(如果没有使用分配,则可以保留原样)这也解决了其他编译器问题:
如果有人有类似的问题希望这有帮助。
如果您需要调试内存分配,请查看traceback a pointer in c++ code mmap
...