当前位置: 首页 > 知识库问答 >
问题:

bds 2006 C 隐藏内存管理器冲突 (类新 / 删除 [] 与安西字符串)

娄利
2023-03-14

我使用BDS 2006 Turbo C已经很长时间了,我的一些更大的项目(CAD/CAM、3D gfx引擎和Astronomic计算)偶尔会出现异常(例如,在3-12个月的24/7重载使用中出现一次)。经过大量调试,我发现:

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

此代码通常位于模板内,其中< code>_s也可以是类,因此< code>delete[]此代码应该可以正常工作,但是< code>delete[]对于结构(类看起来可以)不能正常工作。没有抛出异常,内存被释放,但是它以某种方式破坏了内存管理器分配表,在这之后,任何新的分配都可能是错误的(new可能会创建与已分配空间甚至未分配空间重叠的分配,因此偶尔会出现异常)

我发现,如果我将空析构函数添加到_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覆盖(即使它们没有重叠,我认为重新分配txt所需的tempAnsiStringdat重叠)

所以我的问题是:

>

  • 我在代码1,代码2中做错了什么吗?
  • 有没有办法避免安西字符串(重新)分配错误?(但仍在使用它)

    • 经过广泛的调试(在发布问题2之后),我发现AnsiString不会引起问题。它们仅在使用它们时发生。真正的问题可能在于在 OpenGL 客户端之间切换。我有打开/保存对话框,预览矢量图形。如果我禁用这些VCL子窗口的OpenGL使用,则AnsiString内存管理错误将完全消失。我没有坚持什么问题(MFC / VCL窗口之间的不兼容性或更可能我在切换上下文时犯了一些错误,将进一步调查)。关注 打开GL窗口是:
    • 画布客户专区内的主要 VCL 表单 OpenGL
    • 主 MFC 的子项 打开/保存 对话框停靠预览 VCL 窗体打开GL在画布工作区内

    附笔。

      < li >这些错误取决于< code >新建/删除/删除[]使用的数量,而不是分配的尺寸 < li >代码1和代码2错误都是重复的(例如,有一个解析器加载复杂的ini文件,如果ini没有改变,错误出现在同一行) < li >我只在大型项目中发现这些错误(普通源代码

    很抱歉英语/语法不好…任何帮助/结论/建议都很感激。

  • 共有1个答案

    萧自珍
    2023-03-14

    经过广泛的调试,我很好地隔离了这个问题。在尝试对已删除的指针调用任何删除操作后,bds2006Turbo 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);
    

    [编辑1] 进一步升级代码

    好的,我已经改进了类和结构偶数模板的初始化代码,以修复更多的错误案例。将此代码添加到任何结构/类/模板,如果需要,还可以添加功能

    T()     {}
    T(const 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中的回溯指针。。。

     类似资料:
    • Postgres 10和11的插入说明: 关于冲突[冲突目标]冲突行动 我有一张桌子: 而我想做的 但是我得到一个错误: ON CONFLICT DO UPDATE需要推理规范或约束名称提示:例如,ON CONFLICT(column_name) 为什么我必须提供一个确定的目标?如何提供主键或其他列集?

    • 当我尝试安装sonata admin和LiipFunctionalTestBundle时,它给我一个验证器问题, FileLoaderLoadExc0019:可捕获的致命错误:参数1传递给Sonata\AdminBundle\Admin\Admin::setValidator()必须实现接口Symfony\Component\Validator\ValidatorInterface,Liip\Fu

    • 如何自动隐藏或删除DIV的内容。我把一些信息放在一个容器里。 我想显示新消息只有几秒钟,它可以是5,10什么,但然后我想它是空的,添加新消息,显示它,而不是隐藏。我当然知道setTimeout的"诀窍": 但是在这个选项中,我必须通过每个消息传递这个脚本,这不是我要找的。我也尝试过setInterval,但是正如名字所说,它是间隔,所以消息可以在5秒钟内可见,或者如果它到达间隔时间的末尾,甚至可以

    • 归功于 GRUB ,在启动后,内核可以知道可用物理内存的大小。 在实现操作系统时,前 8Mb 字节的物理内存将被内核保留使用,这些内存被用来存放: The kernel 内核 GDT, IDT et TSS Kernel Stack 内核栈 Some space reserved to hardware (video memory, ...) 保留硬件所需空间 Page directory and

    • 问题内容: 我想在Docker上删除容器,但是要删除时发生错误 我下一步删除容器之前,请参阅现有容器列表 我要删除该列表,即 “ training / webapp”, 但发生了一个错误 容器是否在图像中运行? 请帮忙 问题答案: 首先,删除容器名称 结果 删除第二部分,该部分在要删除的容器上列出 二,取出容器 结果 检查配件

    • 我想删除Docker中的容器,但当您想删除时发生错误 删除容器之前的下一步,请查看现有容器的列表 一个我想删除的列表,即“training/webapp”,但发生了一个错误 容器是否在映像中运行? 请帮忙