C++ - использование оператора "new" невозможно во время отладки

Приложение COM+, сборка с MS Visual Studio 6, SP 6 на Windows XP SP 3 и удаленная отладка.

Мой главный вопрос заключается в следующем; почему я не смогу войти в "новое", если смогу "удалить"? Я в основном ищу идеи о том, что я должен изучить.

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

int * iArray = new int [100];
delete [] iArray;

Я говорю "повредить кучу", потому что вывод отладки отображает "heap[dllhost.exe]: неверный адрес, указанный для rtlvalid ateheap" в "delete".

Я могу перейти к вызову delete, и он, кажется, вызывает правильный вызов (находится в DELOP.cpp в...\Microsoft Visual Studio\VC98\CRT\SRC), но по какой-то причине я не могу войти в любой вызов "нового". Я хватаюсь за соломинку здесь, но у меня есть ощущение, что где-то в базе кода кто-то отвергает оператор 'new', и код, на который я смотрю, непреднамеренно использует его. Симптомы релизной сборки, похоже, выделяют память для одной кучи и пытаются удалить ее из другой, по крайней мере, это моя догадка.

РЕДАКТИРОВАТЬ: Ack! Извините всех, я отправил слишком рано, должен был дать больше информации.

Я искал кодовую базу и нашел несколько переопределений, но все они в классах, а не определены глобально. Единственное, чего нет в классе, это следующее:

struct _new_selector 
{

};

inline void* operator new(size_t, void *ptr, _new_selector)
{
    return (ptr); 
}

Но это новое место размещения, и я уверен, что в этой ситуации это не считается. В какую библиотеку я должен вступить для оригинального "нового"? Я предполагаю, что это то же самое, что и "удалить", но если нет, может, у меня просто нет отладочной информации для него?

РЕДАКТИРОВАТЬ 2: Возиться с этим я обнаружил, что при отладочной сборке эта проблема не существует. Я уже изучил библиотеки времени выполнения, для отладки используются /MD и /MDd. Мало того, но я собрал релизную версию с /MDd, чтобы убедиться, что изменений по-прежнему не было. Если посмотреть на карты как отладочной, так и выпускной версий, новый оператор (с его искажением) выглядит следующим образом:

Релиз:

0001: 00061306?? 2 @ YAPAXI @ Z 10062306 f MSVCRTD: MSVCRTD.dll

0002: 00000298 _imp?? 2 @ YAPAXI @ Z 1006e298 MSVCRTD: MSVCRTD.dll

Debug:

0001: 00077d06?? 2 @ YAPAXI @ Z 10078d06 f MSVCRTD: MSVCRTD.dll

0004: 00000ad4 _imp?? 2 @ YAPAXI @ Z 100b5ad4 MSVCRTD: MSVCRTD.dll

Я также проверил оператор удаления:

Релиз:

0001: 000611f0?? 3 @ YAXPAX @ Z 100621f0 для msvcprtd: delop_s.obj

Debug:

0001: 00077bf0?? 3 @ YAXPAX @ Z 10078bf0 f msvcprtd: delop_s.obj

Кроме того, и у меня нет распечатки, но я могу получить ее, если это поможет, разборка нового оператора выглядит одинаково при выпуске и отладке. Так что, я думаю, это не переопределение? Будет ли встроенное переопределение оператора сделать это неверным?

Кроме того, будучи приложением COM+, которое порождает несколько процессов dllhost.exe, возможно ли, чтобы вызов нового оператора перешел в другую DLL или исполняемый файл, а вызов для удаления перешел в противоположную сторону?

2 ответа

Решение

Итак, вот что это закончило.

В программе, над которой я работаю, около тридцати или около того проектов. Некоторые создают libs, другие dll, третьи exes. В любом случае, все это смешалось. Добавьте к этому тот факт, что мы используем ATL и COM, и он начинает быстро сходить с ума. Конечным результатом является то, что некоторые, а не все проекты строятся с определением компилятора _ATL_MIN_CRT, даже если это приложение для настольного компьютера, а не веб-приложение, в котором клиенту необходимо загрузить несколько модулей.

Вот некоторая информация о _ATL_MIN_CRT:

http://support.microsoft.com/default.aspx?scid=kb;EN-US;q166480

http://msdn.microsoft.com/en-us/library/y3s1z4aw%28v=vs.80%29.aspx

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

По сути, модуль A был построен с _ATL_MIN_CRT, а модуль B был построен без него, но имел зависимость от модуля A. Так как он также использует COM, и все было запущено в dllhost.exe, когда модуль B пытался использовать новый оператор, кажется, вышли из своей DLL, чтобы попытаться выделить память в куче. Затем, при вызове удаления, он попытался удалить его в своей DLL. Таким образом, у нас сумасшедшая утечка памяти.

Помните, что удаление _ATL_MIN_CRT исправляет это, но то, что я упоминаю выше, это только мое понимание этого. Это вполне может быть более / менее сложным, но, тем не менее, это была проблема.

Благодаря всем предложениям, они действительно помогли мне найти эту вещь!

Если предположить, что где-то в коде есть перегруженное новое, вы можете проверить несколько вещей.

  1. дизассемблирование кода и поиск имени библиотеки в этом файле, обычно в сборке есть что-то, что даст вам подсказку
  2. Если вы не можете узнать имя библиотеки, проверьте адрес в сборке, которую вы вводите. Затем в окне вывода отладки проверьте адреса загрузки для различных библиотек - это может дать вам подсказку, какую библиотеку проверять
  3. Если вышеупомянутое не помогает, проверьте, можете ли вы создать файл карты для всего проекта. Если вы можете, то вы можете посмотреть адрес в файле карты, и это может помочь
  4. Попробуйте использовать отладочную версию библиотек времени выполнения. Не могу вспомнить, какая опция включала debug_malloc. Это может помочь вам понять, что происходит в куче

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

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