новый объект вызывает повреждение в куче - PullRequest
2 голосов
/ 24 июня 2011

Я несколько дней боролся с проблемой кучи.Сначала отладчик vs 2005 предупредил меня, что, возможно, я повредил кучу после удаления объекта, который я ранее создал.Исследование этой проблемы привело меня к gflags и настройке кучи страниц.После включения этого параметра для моего конкретного изображения, он предположительно указал мне на строку, которая фактически вызывает повреждение.

Gflags идентифицировал конструктор для рассматриваемого объекта как виновника.Объект получается следующим образом:

class POPUPS_EXPORT MLUNumber :  public MLUBase
  {
...
  }
class POPUPS_EXPORT MLUBase : public BusinessLogicUnit
  {
...
  }

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

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

Нарушение доступа возникает из-за повреждения, возникающего на открывающей скобке конструктора, что, по-видимому, связано с неявной инициализацией объекта (?).

Конструктор базового класса (MLUBase) успешно завершает свою работу.

Из копания с окном памяти в версии 2005 года выясняется, что для фактического объекта недостаточно места.Я предполагаю, что достаточно было выделено только для базового класса.

Строка, вызывающая ошибку:

BusinessLogicUnit* biz = new MLUNumber();

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

Ответы [ 5 ]

6 голосов
/ 24 июня 2011

К сожалению, с учетом предоставленной информации невозможно точно диагностировать проблему.

Некоторые вещи, которые вы можете проверить:

  • Убедитесь, что в BusinessLogicUnit есть виртуальный деструктор. При delete объектах через базовый указатель в базовом классе должен присутствовать виртуальный деструктор, чтобы подкласс был должным образом уничтожен.
  • Убедитесь, что вы создаете все исходные файлы с одинаковыми флагами препроцессора и параметрами компилятора. Разница в флагах (возможно, между флагами отладки / выпуска?) Может привести к изменению размера структуры и, следовательно, к несоответствию между размерами, указанными в разных исходных файлах.
  • Некоторые типы повреждения кучи могут остаться незамеченными даже при ваших настройках gflags. Аудит других ваших кучи использует, чтобы попытаться найти источник ваших проблем, а также. В идеале вы должны составить минимальный тестовый набор, который надежно завершится сбоем, но с минимальной активностью, чтобы вы могли сузить причину.
  • Попробуйте чистое решение и восстановите; Я иногда видел, как метались временные метки, и старый объектный файл мог войти с устаревшим определением структуры. Стоит проверить хотя бы :)
2 голосов
/ 24 июня 2011
BusinessLogicUnit* biz = new MLUNumber();

Как удалить память?Используя указатель базового класса?Вы сделали виртуальный деструктор BusinessLogicUnit?Это должно быть virtual.

class BusinessLogicUnit
{
  public:
      //..
      virtual ~BusinessLogicUnit(); //it must be virtual!
};

В противном случае удаление объекта производного класса через указатель базового класса вызывает неопределенное поведение в соответствии со стандартом C ++.

0 голосов
/ 25 июня 2011

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

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

0 голосов
/ 24 июня 2011

Или, может быть, вы делаете что-то подобное?

struct A
{
    SomeType & m_param;

    A(SomeType & param) : m_param(param)
    {
        ...use m_param here...
    }
};

A a(SomeType()); // passing a temporary by reference

Тогда это неопределенное поведение, потому что указанное временное умирает сразу после m_param(param) происходит ..

0 голосов
/ 24 июня 2011

BusinessLogicUnit равно , а не номеру MLUN. Зачем вам выделять этот путь? Вместо BusinessLogicUnit * biz = new BusinessLogicUnit ();

...