У меня проблема с некоторым приложением, написанным на C ++ Builder 6. Через некоторое время работы (неделя, месяц) приложение вылетает и закрывается без какого-либо сообщения об ошибке. В моем журнале приложений незадолго до сбоя я получаю много исключений «Недостаточно памяти».
Я посмотрел на процесс, когда он выбрасывал исключения из памяти (скриншот ниже), и у него было много незафиксированного частного пространства памяти. Что может быть причиной такого поведения?
У меня была такая проблема однажды, пару лет назад. Причиной этого была опция «использовать динамические библиотеки», не отмеченная в опциях компоновщика. Когда я проверил это, проблема исчезла, и наоборот. Тестовое приложение, которое я сделал, просто вызывало «new char [1000000]» и затем удаляло. Память освобождалась каждый раз (без принудительного увеличения памяти в диспетчере задач Windows), но через некоторое время мне не хватило памяти, VMMap показывал точно то же самое. Много зарезервированной частной памяти, но большая ее часть незафиксирована.
Теперь проблема вернулась, но я не могу исправить это так же. Я не знаю, было ли это причиной, но у меня Builder 6 и 2010 установлены на одной машине. Теперь у меня есть только Builder 6, и кажется, что я не могу воспроизвести ошибку с тестовым приложением, как раньше. Эфирным способом кажется, что есть какая-то ошибка менеджера памяти или что-то. CodeGuard не показывает утечки памяти. Когда я создаю блок памяти с «новым», он сразу же отображается в «размере фиксации памяти», а при удалении уменьшается использование памяти, поэтому я предполагаю, что утечки памяти не так, диспетчер задач не показывает много «размер фиксации памяти» ,
Что я могу сделать? Есть ли способ освободить незафиксированную память? Как диагностировать проблему дальше?
Скриншот:
http://i.stack.imgur.com/UKuTZ.jpg
Я нашел способ смоделировать эту проблему и решение.
for(int i=0; i<100; i++)
{
char * b = new char[100000000];
new char;
delete b;
}
Менеджер памяти Borland резервирует блок памяти, размер которого кратен одной странице, которая составляет 4 КБ. При выделении объема памяти, отличного от кратного 4 КБ, есть некоторое свободное пространство, которое borland может использовать для выделения некоторого другого фрагмента памяти. Когда первый блок освобождается, второй по-прежнему сохраняет зарезервированный блок памяти.
На первый взгляд, код должен вызвать утечку памяти всего в 100B, но на самом деле это вызовет исключение выделения памяти после менее чем 16 итераций.
я нашел два решения для этой проблемы. Одним из них является FastMM, он работает, но и доставляет некоторые проблемы.
Второе решение — обмен borlndmm.dll с тем из Embarcadero Rad Studio 2010. Я еще не проверил его полностью, но, похоже, он работает без проблем.
Я должен перенести проект отверстия в RAD 2010, но по некоторым причинам я застрял в Borland 6.
пролог
Хм, интересное поведение … Я должен добавить кое-что, чему я научился на своей шкуре. Я увольняю BCB6 сразу после того, как попробуйте несколько раз, потому что это было слишком много ошибок на мой вкус (по сравнению с BCB5 особенно с AnsiString
с обработкой). Так что я остался с BCB5 долго без проблем. Я использовал его даже для очень больших проектов, таких как CAD / CAM.
Через несколько лет мне пришлось переехать в BDS2006 из-за моего работодателя и начинаются проблемы (некоторые могут быть похожи на ваши). Помимо незначительных ошибок IDE и trace / breakpoint / codeguard, есть более важные вещи, такие как:
менеджер памяти
delete/delete[]
повреждает менеджер памяти, если вызывается дважды для одного и того же указателя без исключения уведомить …struct
ошибка компилятора была самой большой проблемой, которую я имел (в сочетании с delete
)delete
вызов !!! из-за ошибки либо в компиляторе, либо в C ++.но мне повезло и решил это здесь bds 2006 C Скрытые конфликты диспетчера памяти (класс new / delete [] и AnsiString)
неправильная компиляция
Иногда приложение компилируется неправильно, не выдается никакой ошибки, но некоторые строки кода отсутствуют в exe и / или имеют другой порядок, чем в исходном коде. Я видел это иногда и в BCB 5,6. Чтобы решить это:
~,obj,tds,map,exe,...
Остерегайтесь точки останова / трассировки / codeguard вести себя иначе, чем сырое приложение
особенно с многопоточностью приложение ведет себя по-разному во время трассировки и в то время как нет. Также CodeGuard сделать большую разницу (и я не имею в виду замедление выполнения, которое повреждает чувствительное время). Например CodeGuard иногда имеет неприятную привычку выбрасывать исключения из памяти без причины, поэтому некоторые части кода нужно проверять снова и снова, пока не пройдет, иногда, даже если использование mem остается тем же и далеко из памяти
AnsiString
операторы
Есть два типа AnsiString
в VCL нормальное и компонентное свойство. Поэтому целесообразно принять это во внимание, потому что для свойства компонента AnsiString
это операции операторов разные. Попробуйте например что-то вроде
Edit1->Text+="xxx";
также есть еще AnsiString
ошибки оператора как это:
AnsiString version="aaa"+AnsiString("aaa")+"aaa"; // codeguard: array access violation
Импорт старых проектов BCB
Избегайте прямого импорта, если это возможно, он часто создает некоторые неизвестные выделения и ошибки памяти. Я не уверен, почему, но я подозреваю, что импортированные классы окна обрабатываются по-разному, а memleaks связаны с маркером # 1. Лучший способ — создать новое приложение, а также создать / скопировать компоненты и код вручную. Я знаю, что это ключевое слово, но единственный безопасный способ избежать проблем до сих пор не знаю, в чем проблема, но простая замена * .bdsproj не поможет !!! И в * .dfm я не видел ничего подозрительного.