Мой код падает при удалении этого

Я получаю ошибку сегментации при попытке удалить это.

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

Я не понимаю, какие условия могут привести к этой аварии, только время от времени. Примерно в 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.

Войти все

Мое собственное решение состояло в том, чтобы вести массивный журнал строительства / разрушения, поскольку сбой вполне мог произойти во время отладки:

  1. Журнал строительства, в том числе this значение указателя и другие соответствующие данные
  2. Записать уничтожение, в том числе 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 и volatileLONG?

Правильно выровненный и 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).

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