Могут ли объекты быть развернуты до того, как они будут созданы в стеке? - PullRequest
3 голосов
/ 24 февраля 2010

Мы отлаживали странный случай уже несколько дней и несколько изолировали ошибку, но она все еще не имеет никакого смысла. Возможно, кто-нибудь здесь может дать мне подсказку о том, что происходит.

Проблема заключается в нарушении прав доступа в части кода.

В основном у нас есть что-то вроде этого:

void aclass::somefunc() {
  try {
    erroneous_member_function(*someptr);
  } 
  catch (AnException) {
  }
}

void aclass::erroneous_member_function(const SomeObject& ref) {
  // { //<--scope here error goes away
  LargeObject obj = Singleton()->Object.someLargeObj; //<-remove this error goes away

  //DummyDestruct dummy1//<-- this is not destroyed before the unreachable

  throw AnException();

  // } //<--end scope here error goes away 

  UnreachableClass unreachable; //<- remove this, and the error goes away

  DummyDestruct dummy2; //<- destructor of this object is called! 
}

Находясь в отладчике, он выглядит так, как будто он разрушает UnreachableClass, и когда я вставляю объект DummyDestruct, он не уничтожается до вызова странного деструктора. Так что не похоже, что разрушение LargeObject идет не так, как надо.

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

Мой вопрос: кто-нибудь имеет представление о том, что вызывает это и что происходит? У меня есть достаточно полнофункциональный отладчик (Embarcadero RAD studio), но сейчас я не уверен, что с ним делать.

Может кто-нибудь дать мне совет, как поступить?

Обновление:

Я поместил объект DummyDestruct под предложением throw и установил точку останова в деструкторе. Введен деструктор для этого объекта (и только он находится в этом фрагменте кода).

Ответы [ 5 ]

1 голос
/ 24 февраля 2010

Подобные вещи иногда случаются из-за записи через неинициализированные указатели, за пределами доступа к массиву и т. Д. Точка, в которой возникает ошибка, может быть удалена из места, где она проявляется. Однако, основываясь на описанных вами симптомах, кажется, что он локализован в этой функции. Может ли конструктор копирования LargeObject работать неправильно? Используется ли ссылка? Возможно, somePtr не указывает на действительный SomeObject. Singleton() возвращает указатель на действительный объект? Также возможна ошибка компилятора, особенно при включенной агрессивной оптимизации. Я бы попытался воссоздать ошибку без оптимизации.

1 голос
/ 24 февраля 2010

Время отрабатывать мои навыки телепатической отладки:

Мое лучшее предположение, что ваше приложение имеет ошибку повреждения стека. Это может записать ненужную информацию в стеке вызовов, что означает, что отладчик неправильно сообщает о функции, когда вы прерываете работу, и на самом деле это не деструктор. Либо это, либо вы неправильно интерпретируете информацию отладчика, и объект действительно уничтожается правильно, но вы не знаете, почему!

Если дело в повреждении стека, вам будет очень тяжело разобраться, в чем причина. Вот почему так важно внедрять тонны диагностики (например, подтверждений) в вашу программу, чтобы вы могли уловить повреждение стека, когда оно происходит, вместо того, чтобы зацикливаться на его странных побочных эффектах.

1 голос
/ 24 февраля 2010

С информацией, которую вы предоставили, и если все так, как вы заявляете, единственный возможный ответ - ошибка в компиляторе / оптимизаторе. Просто добавьте дополнительную область с комментарием (это, опять же, если все точно так, как вы заявили).

0 голосов
/ 24 февраля 2010

Вот еще одна дикая догадка, так как вы упомянули строки. Мне известна, по крайней мере, одна реализация, в которой (STL) копирование строки выполняется ленивым образом (т. Е. Фактическое копирование содержимого строки не происходит до тех пор, пока не будет внесено изменение; «копирование» выполняется просто при наличии целевого строкового объекта указать на тот же буфер, что и источник). В этой конкретной реализации (GNU) существует ошибка, из-за которой чрезмерное копирование приводит к тому, что счетчик ссылок (сколько объектов использует одну и ту же фактическую строковую память после предположительно копирующего ее) переключается на 0, что приводит к всевозможным неприятностям. Я сам не сталкивался с этой ошибкой, но кто-то сказал мне об этом. (Я говорю это потому, что можно подумать, что счетчик ссылок будет 32-битным числом, и шансы на то, что он когда-либо перевернется, будут, по меньшей мере, довольно малы, поэтому я не могу описать проблему должным образом.)

0 голосов
/ 24 февраля 2010

Это может быть очень длинный выстрел, но я все равно собираюсь его выпустить ...

Вы говорите, что используете borland - какая версия? И вы говорите, что видите ошибку в строке - STL? Вы вообще включили winsock2 в свой проект?

Причина, по которой я спрашиваю, состоит в том, что у меня возникла проблема при использовании borland 6 (2002) и winsock - заголовок, казалось, испортил упаковку структуры и означал, что разные блоки перевода имели разное представление о структуре памяти std :: string в зависимости от того, какие заголовки были включены модулем перевода, с предсказуемо катастрофическими результатами.

...