Сбои при освобождении могут быть болезненными: это не должно происходить, а когда это происходит, код слишком сложен, чтобы легко найти решение.
Примечание: использование InterlockedDecrement
заставит меняпредположим, что вы работаете в Windows.
Записывайте все
Мое собственное решение состояло в том, чтобы в массовом порядке регистрировать строительство / разрушение, поскольку сбой вполне мог произойти при отладке:
- Записать конструкцию, включая значение указателя
this
и другие соответствующие данные - Записать уничтожение, включая значение указателя
this
и другие соответствующие данные
ЭтоКстати, вы сможете увидеть, был ли this
освобожден дважды или даже выделен вообще.
... все, включая стек
Моя проблема произошла в Managed C ++/ .NET код, означающий, что у меня был легкий доступ к стеку, что было благословением.Кажется, вы работаете на простом C ++, поэтому получение стека может быть непростой задачей, но, тем не менее, это остается очень и очень полезным.
Вы должны попытаться загрузить код из Интернета, чтобы распечатать текущий стек для каждого журнала.Я помню, как играл с http://www.codeproject.com/KB/threads/StackWalker.aspx для этого.
Обратите внимание, что вам нужно либо быть в отладочной сборке, либо иметь файл PDB вдоль исполняемого файла, чтобы убедиться, что стек будет полностьюнапечатано.
... все, включая множественные сбои
Я полагаю, что вы работаете в Windows: вы можете попытаться поймать исключение SEH.Таким образом, если происходит несколько сбоев, вы увидите их все, вместо того, чтобы видеть только первое, и каждый раз вы сможете пометить «OK» или «CRASHED» в своих журналах.Я даже дошел до того, что использовал карты для запоминания адресов распределений / освобождений, организовав таким образом журналы, чтобы показать их вместе (а не последовательно).
Я дома, поэтому не могу предоставить вамточный код, но здесь Google - ваш друг, но следует помнить, что у вас не может быть повсеместно обработчик __try
/ __except
(обработчики разматывания C ++ и исключения C ++ не совместимы с SEH), поэтому выПридется написать промежуточную функцию, чтобы перехватить исключение SEH.
Связано ли это с потоком аварийного завершения?
Последнее, но не менее важное: «У меня бывает только 5% времени»Симптом может быть вызван различными исполнениями пути к коду или тем, что несколько потоков воспроизводятся вместе с одними и теми же данными.
Часть InterlockedDecrement
беспокоит меня: ваш объект живет в несколькихпотоки?Правильно ли выровнен m_nRefCount и volatile
LONG
?
Правильно ли выровнены и LONG
часть важны, здесь.
Если ваша переменная не является LONG
(например,, это может быть size_t
, который не является LONG
в 64-битной Windows), тогда функция вполне может работать неправильно.
То же самое можно сказать о переменной, не выровненнойна 32-байтовых границах.Есть ли в вашем коде #pragma pack()
инструкции?Изменяет ли ваш файл projet выравнивание по умолчанию (я полагаю, вы работаете в Visual Studio)?
Для части volatile
InterlockedDecrement
создает барьер для чтения / записи, поэтому volatile
часть не должна быть обязательной (см. http://msdn.microsoft.com/en-us/library/f20w0x5e.aspx).