Что может вызвать удаление в цикле 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, прерывая все, что делал ваш поток, и в основном теперь ничего не делая, пока ваш процесс не завершится. Первое, что я бы отладил, - это пошаговое прохождение кода вашего деструктора и просмотр того, что он делает.