BDS 2006年Ç隐藏的内存管理器冲突(类新/删除[]与AnsiString类型)BDS 2006

2019-05-08 17:09发布

我使用BDS 2006年的Turbo C ++很长一段时间了,我的一些更大的项目(CAD / CAM,三维 GFX引擎和天文计算)的偶尔在3-12个月内全天候重型使用的抛出异常(例如一次)。 大量的调试后,我发现这一点:

//code1:
struct _s { int i; }    // any struct
_s *s=new _s[1024];     // dynamic allocation
delete[] s;             // free up memory

这个代码通常是内部模板,其中_s可也因此类delete[]这个代码应能正常工作,但delete[]不正确的结构工作(类看起来OK)。 没有例外被抛出,内存被释放,但它在某种程度上损害了内存管理器分配表,并在此之后的任何新的分配可能是错的(新可以创建与已经分配的空间,甚至未分配的空间,因此偶尔的例外重叠分配)

我发现,如果我添加空的析构函数_s不是突然似乎一切OK

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

所以我的问题是:

  1. 我做一些错误的代码1,代码2?
  2. 有没有办法避免AnsiString (再)分配错误? (但仍在使用它)

    • 大量的调试后(张贴问题2后),我发现AnsiString不会产生问题。 他们只在使用它们发生。 真正的问题可能是在OpenGL客户端之间切换。 我打开/保存对话框与预览矢量图形。 如果我禁用的OpenGL使用这些VCL子窗口比AnsiString的内存管理错误完全消失。 我不是托是什么问题(MFC / VCL窗口或者更可能我做了在切换上下文的一些失误,将进一步调查之间的不兼容)。 值得关注的OpenGL窗口是:
    • 里面主要VCL表格+ 的OpenGL Canvas客户区
    • 里面主要MFC打开/保存对话框的孩子+对接的预览VCL表格+ 的OpenGL Canvas客户区

PS

  1. 这些错误取决于数量的new/delete/delete[]用法不上分配的大小
  2. 两个代码1和代码2的错误是重复的(例如具有解析器加载复杂ini文件和在同一行上,如果INI不改变发生错误)
  3. 我只检测大项目(普通源代码> 1MB)与组合使用这些错误AnsiString和模板的内部动态分配,但可能他们也是比较简单的项目,但出现如此罕见,我错过它。
  4. 感染的项目规格:
    • 的win32 noinstall独立(使用Win7sp1 64,但是,XPSP3 X32行为相同)
    • 不计,如果使用GDIOpenGL / GLSL
    • 不计,如果使用设备驱动程序的DLL S,或不
    • 没有OCX,或非标准的VCL组件
    • 没有的DirectX
    • 1个字节对齐编译/链接
    • 不使用RTL,包或框架(单机)

对不起,我英语不好/语法...任何帮助/结论/建议表示赞赏。

Answer 1:

大量的调试后,我精细分离的问题。 BDS2006的Turbo C ++的内存管理成为腐败的尝试调用任何删除后已被删除的指针。 例如:

BYTE *dat=new BYTE[10],*tmp=dat;
delete[] dat;
delete[] tmp;

在此之后是内存管理不可靠的。 (“新”可分配已经分配的空间)

当然,同一个指针的缺失两次是在编程方面的错误,但我已经找到了我的所有问题,产生这个问题(没有在源代码中任何明显的bug)看到这段代码的真正原因:

//---------------------------------------------------------------------------
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()被调用类的析构两次。 一旦真正和一次复印件,因为我忘记创建构造函数

test::test(test &x);

的代码[EDIT1]进一步升级

确定人有我精两个class和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使用它里面的动态分配,如果不使用分配可以保留原样

这也解决这样的其他编译器的问题:

  • 太多的初始化错误在bcc32一个简单的数组

如果有人有类似的问题,希望这有助于。

另外,也要看看回溯在C ++代码的指针mmap如果你需要调试内存分配...



文章来源: bds 2006 C hidden memory manager conflicts (class new / delete[] vs. AnsiString)