Что может вызвать удаление в цикле Sleep() и никогда не возвращаться в Borland / Embarcadero RTL?

У меня есть странная ошибка, когда при удалении одного конкретного объекта, delete никогда не вернется. Вместо этого он, кажется, тратит свое время на звонки Sleep() в постоянном цикле. Вот стек вызовов:

:7723fd71 ntdll.ZwDelayExecution + 0x15
:767c4498 KERNELBASE.Sleep + 0xf
:21495359 BORLNDMM.@Borlndmm@SysFreeMem$qqrpv + 0xb5
:32aaa3e5 CC32100MT._free + 0xd
:32a020b2 CC32100MT.@$bdele$qpv + 0x1e
[My code]

Запуск, он возвращается к SysFreeMem (никогда не возвращаться к free) и звонки Sleep опять изнутри SysFreeMemпостоянно зацикливается.

Мой код довольно прост: это обработчик событий VCL, спинбокс только что изменился, объект настроек обновился, а сделанные временные настройки были удалены:

delete poNewSettings;

Этот код не менялся в течение года или двух, а также некоторое время не имел класса настроек, который по сути является гигантским структурным объектом, содержащим множество настроек. У него есть деструктор, сгенерированный компилятором. Пошаговое выполнение кода показывает количество вызовов, удаляющих строки и другие объекты std::, а затем он останавливается при переходе к следующей функции (то есть в конце ~basic_string(), нажав F7 на закрывающей скобке }), который IDE никогда не показывает. Замораживание в том, что это внутри Sleep(). Этот код выполняется в главном потоке.

Я попытался использовать представление ЦП для определения задержки, с которой вызывался Sleep (), но не смог определить ее - я боюсь, я не до конца разбираюсь в коде сборки x86.

Еще одна нить внутри Sleep, вероятно, связано с COM (приложение является COM-сервером, хотя в настоящее время COM не использует ничего). Весь его стек вызовов:

:7723fd71 ntdll.ZwDelayExecution + 0x15
:767c4498 KERNELBASE.Sleep + 0xf
:74c7d98d ; C:\Windows\syswow64\ole32.dll
:74c7d87a ; C:\Windows\syswow64\ole32.dll
:768133aa kernel32.BaseThreadInitThunk + 0x12
:77259ef2 ntdll.RtlInitializeExceptionChain + 0x63
:77259ec5 ntdll.RtlInitializeExceptionChain + 0x36

Еще один поток делает что-то и активно выделяет и освобождает память и вызывает Sleep() тоже - выполняется фоновая задача, которая проверяет, должна ли она работать (не обязательно), и спит в течение 100 мс, чтобы проверить снова. Выделение и освобождение для строки для пути к папке. Хотя в программе есть другие потоки, все они заблокированы, ожидая что-то сделать, на этот раз используя WaitForSingleObject или похожие. Этот поток фоновых задач активируется (возвращается из режима сна) каждые 100 мс; Я не вижу (пока!) Как это может повлиять на delete,

Насколько я могу судить, никакие другие потоки ничего не удаляют и не выделяют. Я ставлю точки останова в CC32100MT._malloc, CC32100MT._free а также CC32100MT._realloc, Никто не прерывает работу во время работы, а когда он приостановлен для проверки, никакие другие потоки не находятся ни в одном из этих вызовов.

Что может быть причиной удаления зацикливания и не возврата?

Я использую: * RAD Studio 2010, полностью обновленный * Приложение в основном C++ (C++ Builder) с небольшими кусочками Delphi. * Поскольку он использует Embarcadero RTL, я думаю, что он использует FastMM

Я добавил тег Delphi, так как он использует Embarcadero RTL и FastMM, которые используются людьми Delphi гораздо чаще, чем людьми C++.

1 ответ

Я не уверен на 100%, что в этом случае вы можете доверять отладчику в IDE RAD Studio, чтобы правильно называть соответствующие символы ядра.

Я думаю, что вы должны войти в место, где это происходит, а затем проверить переменную, которую вы освобождаете, и посмотреть, не была ли она повреждена.

Если переменная, которую вы освобождаете, является классом, который вы определили сами, я обычно люблю добавлять поля Guard в начало и конец объекта.

class TMyPOSettings {
  public:
    ...
  private:
    int Guard1;
    // all my other instance data 
    int Guard2
};

В конструкторе я установил параметры защиты MAGIC1 и MAGIC2, которые я где-то определил, а в деструкторе я установил параметры защиты MAGIC_FREE_1 и MAGIC_FREE_2.

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

Интересно, возможно ли, что то, что вы отлаживаете, на самом деле является результатом кода после того, как серьезное исключение обнаруживается внутри Windows, прерывая все, что делал ваш поток, и в основном теперь ничего не делая, пока ваш процесс не завершится. Первое, что я бы отладил, - это пошаговое прохождение кода вашего деструктора и просмотр того, что он делает.

Другие вопросы по тегам