bds 2006 C隐藏的内存管理器发生冲突(类new/delete []与AnsiString) [英] bds 2006 C hidden memory manager conflicts (class new / delete[] vs. AnsiString)

查看:92
本文介绍了bds 2006 C隐藏的内存管理器发生冲突(类new/delete []与AnsiString)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很长时间以来一直在使用 BDS 2006 Turbo C ++ ,而我的一些更大的项目( CAD/CAM,3D gfx引擎和天文计算)有时会例外(例如,在24/7的24/7重型使用情况下每3-12个月一次).经过广泛的调试,我发现了这一点:

I am using BDS 2006 Turbo C++ for a long time now and some of my bigger projects (CAD/CAM,3D gfx engines and Astronomic computations) occasionally throw an exception (for example once in 3-12 months of 24/7 heavy duty usage). After extensive debugging I found this:

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

此代码通常在模板内,其中_s也可以是类,因此delete[]此代码应正常工作,但delete[]对于结构不能正常工作(类看起来不错).

this code is usually inside template where _s can be also class therefore delete[] this code should work properly, but the delete[] does not work properly for structs (classes looks OK). No exceptions is thrown, the memory is freed, but it somehow damages the memory manager allocation tables and after this any new allocation can be wrong (new can create overlapped allocations with already allocated space or even unallocated space hence the occasional exceptions)

我发现,如果我向_s添加空析构函数,那么突然看来一切正常

I have found that if I add empty destructor to _s than suddenly seems everything OK

struct _s { int i; ~_s(){}; }

现在,怪异的部分出现了.将其更新到我的项目后,我发现AnsiString类也有错误的重新分配.例如:

Well now comes the weird part. After I update this to my projects I have found that AnsiString class has also bad reallocations. For example:

//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必须重新分配几次,有时txt数据会被txt覆盖(即使它们没有重叠,我认为重新分配txt所需的临时AnsiString也与dat)重叠

In this code dat contains some useful data, then later is some txt string created by adding lines so the txt must be reallocated few times and sometimes the dat data is overwritten by txt (even if they are not overlapped, I thing the temp AnsiString needed to reallocate txt is overlapped with dat)

所以我的问题是:

  1. 我在代码1,代码2中做错了吗?
  2. 有什么办法可以避免AnsiString(重新)分配错误? (但仍在使用)

  1. Am I doing something wrong in code1, code2 ?
  2. Is there any way to avoid AnsiString (re)allocation errors ? (but still using it)

  • 经过大量调试(在发布问题2之后),我发现AnsiString不会引起问题.它们仅在使用它们时发生.真正的问题可能是在 OpenGL 客户端之间切换.我有带有矢量图形预览的打开/保存"对话框.如果我为这些 VCL 子窗口禁用 OpenGL 使用,则AnsiString内存管理错误将完全消失.我不是问题所在( MFC/VCL 窗口之间的不兼容,或者我在切换上下文时可能犯了一些错误,将会进一步调查).关注的 OpenGL 窗口是:
  • Canvas客户区域内的主要 VCL 表单+ OpenGL
  • MFC 的子级<打开/保存对话框+停靠的预览 VCL 表单+ OpenGL Canvas客户区域内
  • After extensive debugging (after posting question 2) I have found that AnsiString do not cause problems. They only occur while using them. The real problem is probably in switching between OpenGL clients. I have Open/Save dialogs with preview for vector graphics. If I disable OpenGL usage for these VCL sub-windows than AnsiString memory management errors disappears completely. I am not shore what is the problem (incompatibility between MFC/VCL windows or more likely I made some mistake in switching contexts, will further investigate). Concern OpenGL windows are:
  • main VCL Form + OpenGL inside Canvas client area
  • child of main MFC Open/Save dialog + docked preview VCL Form + OpenGL inside Canvas client area

PS

  1. 这些错误取决于new/delete/delete[]使用次数,而不取决于分配的大小
  2. code1和code2错误都是重复的(例如,有一个解析器来加载复杂的ini文件,并且如果不更改ini,该错误会在同一行上发生)
  3. 我仅在结合使用AnsiString和具有内部动态分配的模板的大型项目(纯源代码> 1MB)中检测到这些错误,但是有可能它们也出现在较简单的项目中,但是很少发生,我会错过它
  4. 受感染的项目规格:
    • win32 noinstall独立版本(使用 Win7sp1 x64 ,但在 XPsp3 x32 上的行为相同)
    • 如果使用 GDI OpenGl/GLSL
    • 不计量
    • 如果不使用设备驱动程序 DLL ,则不计量
    • 没有 OCX ,或非标准的 VCL 组件
    • DirectX
    • 1字节对齐的编译/链接
    • 请勿使用 RTL ,程序包或框架(独立)
  1. these errors depend on number of new/delete/delete[] usages not on the allocated sizes
  2. both code1 and code2 errors are repetitive (for example have a parser to load complex ini file and the error occurs on the same line if the ini is not changed)
  3. I detect these errors only on big projects (plain source code > 1MB) with combined usage of AnsiString and templates with internal dynamic allocations, but is possible that they are also in simpler projects but occurs so rarely that I miss it.
  4. Infected projects specs:
    • win32 noinstall standalone (using Win7sp1 x64 but on XPsp3 x32 behaves the same)
    • does not meter if use GDI or OpenGl/GLSL
    • does not meter if use device driver DLLs or not
    • no OCX,or nonstandard VCL component
    • no DirectX
    • 1 Byte aligned compilation/link
    • do not use RTL,packages or frameworks (standalone)

很抱歉英语/语法不好... 任何帮助/结论/建议表示赞赏.

Sorry for bad English/grammar ... any help / conclusion / suggestion appreciated.

推荐答案

经过广泛的调试,我很好地隔离了问题. 尝试为已删除的指针调用任何删除操作后,bds2006 Turbo C ++的内存管理已损坏.例如:

After extensive debugging i finely isolated the problem. Memory management of bds2006 Turbo C++ became corrupt after you try to call any delete for already deleted pointer. for example:

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

在此之后,内存管理不可靠. (新"可以分配已经分配的空间)

After this is memory management not reliable. ('new' can allocate already allocated space)

当然,两次删除同一指针是程序员方面的错误,但是我发现了所有导致此问题的真正原因(在源代码中没有任何明显的错误),请参见以下代码:

Of course deletion of the same pointer twice is bug on programmers side, but i have found the real cause of all my problems which generates this problem (without any obvious bug in source code) see this code:

//---------------------------------------------------------------------------
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,一次是它的副本,因为我忘记创建构造函数

In function get() is called destructor for class a twice. Once for real a and once for its copy because I forget to create constructor

test::test(test &x);

[Edit1]进一步的代码升级

好的,我已经完善了类和结构甚至模板的初始化代码,以修复更多的错误情况.将此代码添加到任何struct/class/template,并在需要时添加功能

OK I have refined the initialization code for both class and struct even templates to fix even more bug-cases. Add this code to any struct/class/template and if needed than add functionality

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在其中使用动态分配时才需要最后一个运算符.

    • T is the struct/class name
    • the last operator is needed only if T uses dynamic allocations inside it if no allocations are used you can leave it as is
    • 这也解决了其他编译​​器问题,例如:

      This also resolves other compiler issues like this:

      如果有人遇到类似的问题,希望对您有所帮助.

      If anyone have similar problems hope this helps.

      如果您需要调试内存分配,还可以查看使用c ++代码mmap 中的指针回溯...

      Also look at traceback a pointer in c++ code mmap if you need to debug your memory allocations...

      这篇关于bds 2006 C隐藏的内存管理器发生冲突(类new/delete []与AnsiString)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆