windows — Недостаточно адресного пространства виртуальной памяти (программа Borland C ++ Builder 6)

У меня проблема с некоторым приложением, написанным на C ++ Builder 6. Через некоторое время работы (неделя, месяц) приложение вылетает и закрывается без какого-либо сообщения об ошибке. В моем журнале приложений незадолго до сбоя я получаю много исключений «Недостаточно памяти».
Я посмотрел на процесс, когда он выбрасывал исключения из памяти (скриншот ниже), и у него было много незафиксированного частного пространства памяти. Что может быть причиной такого поведения?

У меня была такая проблема однажды, пару лет назад. Причиной этого была опция «использовать динамические библиотеки», не отмеченная в опциях компоновщика. Когда я проверил это, проблема исчезла, и наоборот. Тестовое приложение, которое я сделал, просто вызывало «new char [1000000]» и затем удаляло. Память освобождалась каждый раз (без принудительного увеличения памяти в диспетчере задач Windows), но через некоторое время мне не хватило памяти, VMMap показывал точно то же самое. Много зарезервированной частной памяти, но большая ее часть незафиксирована.

Теперь проблема вернулась, но я не могу исправить это так же. Я не знаю, было ли это причиной, но у меня Builder 6 и 2010 установлены на одной машине. Теперь у меня есть только Builder 6, и кажется, что я не могу воспроизвести ошибку с тестовым приложением, как раньше. Эфирным способом кажется, что есть какая-то ошибка менеджера памяти или что-то. CodeGuard не показывает утечки памяти. Когда я создаю блок памяти с «новым», он сразу же отображается в «размере фиксации памяти», а при удалении уменьшается использование памяти, поэтому я предполагаю, что утечки памяти не так, диспетчер задач не показывает много «размер фиксации памяти» ,

Что я могу сделать? Есть ли способ освободить незафиксированную память? Как диагностировать проблему дальше?

Скриншот:
http://i.stack.imgur.com/UKuTZ.jpg

3

Решение

Я нашел способ смоделировать эту проблему и решение.

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.

3

Другие решения

пролог

Хм, интересное поведение … Я должен добавить кое-что, чему я научился на своей шкуре. Я увольняю BCB6 сразу после того, как попробуйте несколько раз, потому что это было слишком много ошибок на мой вкус (по сравнению с BCB5 особенно с AnsiStringс обработкой). Так что я остался с BCB5 долго без проблем. Я использовал его даже для очень больших проектов, таких как CAD / CAM.

Через несколько лет мне пришлось переехать в BDS2006 из-за моего работодателя и начинаются проблемы (некоторые могут быть похожи на ваши). Помимо незначительных ошибок IDE и trace / breakpoint / codeguard, есть более важные вещи, такие как:

  1. менеджер памяти

    • delete/delete[] повреждает менеджер памяти, если вызывается дважды для одного и того же указателя без исключения уведомить …
    • неправильный конструктор / деструктор по умолчанию за struct ошибка компилятора была самой большой проблемой, которую я имел (в сочетании с delete)
    • неправильные или отсутствующие функции-члены в классах могут вызвать несколько delete вызов !!! из-за ошибки либо в компиляторе, либо в C ++.

    но мне повезло и решил это здесь bds 2006 C Скрытые конфликты диспетчера памяти (класс new / delete [] и AnsiString)

  2. неправильная компиляция

    Иногда приложение компилируется неправильно, не выдается никакой ошибки, но некоторые строки кода отсутствуют в exe и / или имеют другой порядок, чем в исходном коде. Я видел это иногда и в BCB 5,6. Чтобы решить это:

    1. удалить все временные файлы, такие как ~,obj,tds,map,exe,...
    2. закройте IDE и снова откройте его, чтобы быть уверенным (иногда просмотр локальных переменных (в основном больших массивов) поврежденной памяти IDE)
    3. снова скомпилировать
  3. Остерегайтесь точки останова / трассировки / codeguard вести себя иначе, чем сырое приложение

    особенно с многопоточностью приложение ведет себя по-разному во время трассировки и в то время как нет. Также CodeGuard сделать большую разницу (и я не имею в виду замедление выполнения, которое повреждает чувствительное время). Например CodeGuard иногда имеет неприятную привычку выбрасывать исключения из памяти без причины, поэтому некоторые части кода нужно проверять снова и снова, пока не пройдет, иногда, даже если использование mem остается тем же и далеко из памяти

  4. AnsiString операторы

    Есть два типа AnsiString в VCL нормальное и компонентное свойство. Поэтому целесообразно принять это во внимание, потому что для свойства компонента AnsiStringэто операции операторов разные. Попробуйте например что-то вроде

    Edit1->Text+="xxx";
    

    также есть еще AnsiString ошибки оператора как это:

    AnsiString version="aaa"+AnsiString("aaa")+"aaa";       // codeguard: array access violation
    
  5. Импорт старых проектов BCB

    Избегайте прямого импорта, если это возможно, он часто создает некоторые неизвестные выделения и ошибки памяти. Я не уверен, почему, но я подозреваю, что импортированные классы окна обрабатываются по-разному, а memleaks связаны с маркером # 1. Лучший способ — создать новое приложение, а также создать / скопировать компоненты и код вручную. Я знаю, что это ключевое слово, но единственный безопасный способ избежать проблем до сих пор не знаю, в чем проблема, но простая замена * .bdsproj не поможет !!! И в * .dfm я не видел ничего подозрительного.

0

По вопросам рекламы [email protected]