Мой код падает при удалении этого - PullRequest
2 голосов
/ 16 сентября 2011

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

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

Я не понимаю, какие условия могут привести к этой аварии, только время от времени. Примерно в 95% случаев код работает идеально, но иногда кажется, что он как-то поврежден и вылетает.

Кстати, деструктор класса ничего не делает.

Должен ли я предположить, что что-то портит мою кучу где-то еще и что указатель this как-то испорчен?

Редактировать: По запросу код сбоя:

long CImageBuffer::Release()
{
  long nRefCount = InterlockedDecrement(&m_nRefCount);
  if(nRefCount == 0)
  {
    delete this;
  }
  return nRefCount;
}

Объект был создан с новым, его нет ни в одном массиве.

Ответы [ 3 ]

1 голос
/ 16 сентября 2011

Похоже, вы не соответствовали new и delete. Обратите внимание, что delete this; может использоваться только для объекта, который был выделен с использованием new (и в случае переопределенного operator new или нескольких копий среды выполнения C ++, конкретного new, который соответствует delete, найденного в текущая область)

1 голос
/ 16 сентября 2011

Самый очевидный ответ: не удаляйте это.

Если вы настаиваете на этом, используйте обычные способы поиска ошибок:
1. используйте valgrind (или аналогичный инструмент), чтобы найти проблемы с доступом к памяти
2. написать юнит-тесты
3. использовать отладчик (подготовьтесь к долгому взгляду на экран - зависит от того, насколько велик ваш проект)

0 голосов
/ 18 сентября 2011

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

Примечание: использование 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 и 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).

...