Я использую 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
может быть также классом, поэтому 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
)
Итак, мои вопросы:
- Я делаю что-то не так в code1, code2?
Есть ли способ избежать ошибок
AnsiString
(пере)распределения? (но до сих пор пользуюсь)- 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 thanAnsiString
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: - главная форма VCL + OpenGL внутри
Canvas
клиентской области - дочерний элемент основного диалогового окна MFC Open/Save + закрепленная форма предварительного просмотра VCL + OpenGL внутри
Canvas
клиентской области
- After extensive debugging (after posting question 2) I have found that
P.S.
- эти ошибки зависят от количества
new/delete/delete[]
использований, а не от выделенных размеров - ошибки code1 и code2 повторяются (например, есть анализатор для загрузки сложного ini-файла, и ошибка возникает в той же строке, если ini не изменен)
- Я обнаруживаю эти ошибки только в больших проектах (обычный исходный код > 1 МБ) с комбинированным использованием
AnsiString
и шаблонов с внутренними динамическими выделениями, но возможно, что они есть и в более простых проектах, но происходят так редко, что я их пропускаю. - Infected projects specs:
- win32 noinstall standalone (using Win7sp1 x64 but on XPsp3 x32 behaves the same)
- не измеряет при использовании GDI или OpenGl/GLSL
- не измеряет, используются ли драйверы устройств DLL или нет
- нет компонента OCX или нестандартного компонента VCL
- нет DirectX
- Компиляция/ссылка с выравниванием по 1 байту
- не используйте RTL, пакеты или фреймворки (отдельно)
Извините за плохой английский/грамматику... любая помощь/вывод/предложение приветствуется.