У меня есть небольшое однопотоковое приложение на С++, скомпилированное и связанное с использованием Visual Studio 2005, которое использует boost (crc, program_options и tokenizer), небольшое количество STL и различные другие системные заголовки.
(Основная цель - прочитать в .csv и сгенерировать пользовательский двоичный файл .dat и парные .h объявляющие структуры, которые "объясняют" формат .dat.)
Инструмент сбой (нарушение доступа в NULL) при запуске вне отладчика, только в версии. Например. нажатие F5 не приводит к сбою инструмента, Ctrl-F5. Когда я снова присоединяю отладчик, я получаю этот стек:
[email protected]() + 0x26916 bytes
csv2bin.exe!malloc(unsigned int size=0x00000014) Line 163 + 0x63 bytes C
csv2bin.exe!operator new(unsigned int size=0x00000014) Line 59 + 0x8 bytes C++
>csv2bin.exe!Record::addField(const char * string=0x0034aac8) Line 62 + 0x7 bytes C++
csv2bin.exe!main(int argc=0x00000007, char * * argv=0x00343998) Line 253 C++
csv2bin.exe!__tmainCRTStartup() Line 327 + 0x12 bytes C
Линия, с которой он врезался, выглядит несколько безобидно:
pField = new NumberField(this, static_cast<NumberFieldInfo*>(pFieldInfo));
... Я не верю, что он дошел до конструктора, он просто выделил память перед тем, как перейти к конструктору. Он также выполнил этот код десятки раз к моменту его сбоя, обычно в последовательном (но в остальном не подозрительном) месте.
Проблема исчезает при компиляции с /MTd или/MDd (время отладки) и возвращается при использовании /MT или/MD.
NULL загружается из стека, и я вижу его в виде памяти. _RtlAllocateHeap @12 + 0x26916 байтов кажется огромным смещением, так как был сделан неправильный переход.
Я пробовал _HAS_ITERATOR_DEBUGGING
в сборке отладки, и это не вызвало ничего подозрительного.
Удаление HeapValidate в начале и конце записи:: addField показывает кучу OK вплоть до сбоя.
Это работало - я не совсем уверен, что изменилось между теперь и в последний раз, когда мы скомпилировали инструмент (возможно, много лет назад, возможно, под старым VS). Мы попробовали более старую версию boost (1.36 против 1.38).
Прежде чем перейти к ручному исследованию кода или подавать его на PC-Lint и расчесывать его вывод, какие-либо предложения по эффективному отладке этого?
[Я буду рад обновить вопрос с дополнительной информацией, если вы запросите информацию в комментариях.]