Мой код падает при удалении этого
Я получаю ошибку сегментации при попытке удалить это.
Я знаю, что вы думаете об удалении этого, но это было оставлено моим предшественником. Я знаю о некоторых мерах предосторожности, которые я должен предпринять, которые были проверены и приняты.
Я не понимаю, какие условия могут привести к этой аварии, только время от времени. Примерно в 95% случаев код работает идеально, но иногда кажется, что он как-то поврежден и вылетает.
Деструктор класса ничего не делает между прочим.
Должен ли я предположить, что что-то портит мою кучу где-то еще и что этот указатель как-то испорчен?
Изменить: По запросу код сбоя:
long CImageBuffer::Release()
{
long nRefCount = InterlockedDecrement(&m_nRefCount);
if(nRefCount == 0)
{
delete this;
}
return nRefCount;
}
Объект был создан с новым, он не находится ни в каком виде массива.
3 ответа
Самый очевидный ответ: не удаляйте это.
Если вы настаиваете на этом, используйте обычные способы поиска ошибок:
1. используйте valgrind (или аналогичный инструмент), чтобы найти проблемы с доступом к памяти
2. написать юнит-тесты
3. использовать отладчик (подготовьтесь к долгому взгляду на экран - зависит от того, насколько велик ваш проект)
Кажется, вы не соответствовали new
а также delete
, Обратите внимание, что delete this;
может использоваться только для объекта, который был выделен с помощью new
(и в случае переопределения operator new
или несколько копий среды выполнения C++, конкретный new
это соответствует delete
нашел в текущем объеме)
Сбои при освобождении могут быть болью: это не должно происходить, и когда это происходит, код слишком сложен, чтобы легко найти решение.
Примечание: использование 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).