bds 2006 C конфликты с скрытым диспетчером памяти (class new / delete vs. AnsiString)

Я использую BDS 2006 Turbo C ++ в течение длительного времени, и некоторые из моих больших проектов ( CAD / CAM, 3D- gfx-двигатели и астрономические вычисления) иногда вызывают исключение (например, один раз в 3-12 месяцев 24/7 использования в тяжелых условиях ). После обширной отладки я нашел это:

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

этот код обычно находится внутри шаблона, где _s может быть classом, поэтому delete[] этот код должен работать правильно, но delete[] не работает должным образом для structs (classы выглядят ОК). Никаких исключений не выбрасывается, память освобождается, но она как-то повреждает таблицы распределения памяти диспетчера памяти, и после этого любое новое распределение может быть неправильным (новые могут создавать перекрывающиеся выделения с уже выделенным пространством или даже нераспределенным пространством, следовательно, случайные исключения)

Я обнаружил, что если я добавлю пустой деструктор в _s вдруг кажется, что все ОК

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

Ну, теперь идет странная часть. После того, как я обновил это в своих проектах, я обнаружил, что class 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 (даже если они не перекрываются, я считаю, что для параметра temp AnsiString необходимо перераспределение txt перекрывается с dat )

Поэтому мои вопросы:

  1. Я что-то делаю неправильно в code1, code2?
  2. Есть ли способ избежать ошибок размещения AnsiString (re)? (но все еще используя его)

    • После обширной отладки (после публикации вопроса 2) я обнаружил, что AnsiString не вызывает проблем. Они возникают только при их использовании. Реальная проблема, вероятно, заключается в переключении между клиентами OpenGL . У меня есть диалоговые windows «Открыть / Сохранить» с предварительным просмотром векторной графики. Если я отключу использование OpenGL для этих подкадров VCL, чем ошибки управления памятью AnsiString полностью исчезнут. Я не знаю, в чем проблема (несовместимость между windowsми MFC / VCL или, скорее, я допустил ошибку при переключении контекстов, продолжит исследование). Концерн OpenGL- windows:
    • основная форма VCL + OpenGL внутри области клиента Canvas
    • дочерний элемент главного диалогового windows MFC Open / Save + прикрепленный предварительный просмотр VCL Form + OpenGL внутри области клиента Canvas

PS

  1. эти ошибки зависят от количества new/delete/delete[] применений не по выделенным размерам
  2. как ошибки code1, так и code2 повторяются (например, парсер загружает сложный ini-файл, и ошибка возникает в той же строке, если ini не изменяется)
  3. Я обнаруживаю эти ошибки только в больших проектах (простой исходный код> 1 МБ) при совместном использовании AnsiString и шаблонов с внутренними динамическими распределениями, но возможно, что они также находятся в более простых проектах, но встречаются так редко, что я скучаю по ним.
  4. Инфицированные проекты:
    • win32 noinstall standalone (используя Win7sp1 x64, но на XPsp3 x32 ведет себя одинаково)
    • не учитывается при использовании GDI или OpenGl / GLSL
    • не работает, если используется драйвер устройства DLL или нет.
    • OCX или нестандартный компонент VCL
    • нет DirectX
    • 1 байтовая выровненная компиляция / ссылка
    • не использовать RTL , пакеты или фреймворки (автономные)

Извините за плохой английский / грамматику … любая помощь / заключение / предложение оценены.

После обширной отладки я полностью изолировал проблему. Управление памятью bds2006 Turbo C ++ стало поврежденным после того, как вы попытались вызвать любое удаление для уже удаленного указателя. например:

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

После этого управление памятью не является надежным. («новый» может выделить уже выделенное пространство)

Конечно, удаление одного и того же указателя дважды является ошибкой на стороне программистов, но я нашел истинную причину всех моих проблем, которые порождают эту проблему (без какой-либо очевидной ошибки в исходном коде) см. Этот код:

 //--------------------------------------------------------------------------- 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 

В функции get() называется деструктор для classа a дважды. Один раз для реального и один раз для его копии, потому что я забыл создать конструктор

 test::test(test &x); 

[Edit1] дальнейшее обновление кода

OK Я уточнил код инициализации как для шаблонов classов, так и для структуры, чтобы исправить еще больше ошибок. Добавьте этот код в любой шаблон struct / class / template и при необходимости добавьте функциональность

 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 - имя структуры / classа
  • последний оператор нужен только в том случае, если T использует динамические распределения внутри него, если никакие распределения не используются, вы можете оставить его как есть

Это также устраняет другие проблемы, связанные с компилятором:

  • Слишком много ошибок инициализаторов для простого массива в bcc32

Если у кого-то есть подобные проблемы, надеюсь, что это поможет.

Также посмотрите на traceback указатель в c ++ код mmap если вам нужно отлаживать выделение памяти ...

  • Освобождает выделенную память, необходимую при выходе из программы на C
  • Почему NSNumber такие странные saveCounts?
  • C ++, Free-Store против кучи
  • Как выделена память для статической переменной?
  • Модели управления памятью в C ++
  • Go 1.3 Сборщик мусора, не отбрасывающий серверную память обратно в систему
  • Как я могу получить местоположение памяти объекта в java?
  • R управления памятью / не может выделить вектор размера n Mb
  • Можно ли использовать Инициализатор объектов?
  • Memory Allocation "Ошибка: не может выделить вектор размера 75.1 Mb"
  • Сведения о переполнении памяти Linux
  • Давайте будем гением компьютера.