Я работаю над многопоточным C ++ приложением, которое портит кучу. Обычные инструменты для обнаружения этой коррупции кажутся неприменимыми. Старые сборки (18 месяцев) исходного кода демонстрируют то же поведение, что и самый последний выпуск, так что это было давно и просто не было замечено; с другой стороны, исходные дельты не могут быть использованы для определения момента появления ошибки - в хранилище много изменений кода.
Подсказка для сбойного поведения заключается в создании пропускной способности в этой системе - передача данных через сокет, которая передается во внутреннее представление. У меня есть набор тестовых данных, которые периодически вызывают исключение приложения (в разных местах, по разным причинам, в том числе при сбое выделения кучи, например: повреждение кучи).
Поведение, похоже, связано с мощностью процессора или пропускной способностью памяти; чем больше у каждой машины, тем легче ее разбить. Отключение гиперпоточного ядра или двухъядерного ядра снижает вероятность (но не устраняет) повреждения. Это наводит на мысль о проблеме, связанной со временем.
Теперь вот к чему:
Когда он запускается в облегченной среде отладки (скажем, Visual Studio 98 / AKA MSVC6
), повреждение кучи достаточно легко воспроизвести - проходит десять или пятнадцать минут, прежде чем что-то ужасно выходит из строя и возникают исключения, например alloc;
при работе в сложной среде отладки (Rational Purify). , VS2008/MSVC9
или даже Microsoft Application Verifier) система становится ограниченной по скорости памяти и не дает сбоя (связанная с памятью: ЦП не поднимается выше 50%
, индикатор диска не горит, программа работает так быстро, как может, коробка потребляет 1.3G
2 ГБ ОЗУ). Итак, У меня есть выбор между способностью воспроизвести проблему (но не определить причину) или возможностью определить причину или проблему, которую я не могу воспроизвести.
Мои лучшие догадки о том, куда идти дальше:
- Получить безумно хрюканную коробку (чтобы заменить текущую коробку разработчика: 2 ГБ ОЗУ в
E6550 Core2 Duo
); это позволит воспроизвести сбой, вызывающий неправильное поведение при работе в мощной среде отладки; или
- Перепишите операторы
new
и delete
, чтобы использовать VirtualAlloc
и VirtualProtect
, чтобы пометить память как доступную только для чтения, как только это будет сделано. Запустите под MSVC6
и пусть ОС поймает плохого парня, который пишет в освобожденную память. Да, это знак отчаяния: кто, черт возьми, переписывает new
и delete
?! Интересно, будет ли это так медленно, как при Purify et al.
И, нет: доставка со встроенным прибором Purify невозможна.
Коллега только что прошел мимо и спросил: «Переполнение стека? Мы сейчас получаем переполнение стека?!?»
А теперь вопрос: Как мне найти повреждителя кучи?
Обновление: балансировка new[]
и delete[]
, кажется, прошла долгий путь к решению проблемы. Вместо 15 минут приложение работает примерно за два часа до сбоя. Еще нет. Есть еще предложения? Сохраняется повреждение кучи.
Обновление: сборка релиза под Visual Studio 2008 выглядит значительно лучше; текущее подозрение основано на реализации STL
, которая поставляется с VS98
.
- Воспроизведите проблему.
Dr Watson
создаст дамп, который может быть полезен для дальнейшего анализа.
Я приму это к сведению, но я обеспокоен тем, что доктор Ватсон будет сбит с толку только после факта, а не тогда, когда наваливается куча.
Другой попыткой может быть использование WinDebug
в качестве инструмента отладки, который является достаточно мощным и в то же время легким.
Понятно, что сейчас, опять же, мало помощи, пока что-то не пойдет не так. Я хочу поймать вандала в действии.
Возможно, эти инструменты позволят вам хотя бы сузить проблему до определенного компонента.
Я не очень надеюсь, но отчаянные времена требуют ...
И уверены ли вы, что все компоненты проекта имеют правильные настройки библиотеки времени выполнения (C/C++ tab
, категория Генерация кода в настройках проекта VS 6.0)?
Нет, нет, и завтра я проведу пару часов, изучая рабочее пространство (в нем 58 проектов) и проверяя, все ли они компилируются и связываются с соответствующими флагами.
Обновление: это заняло 30 секунд. Выберите все проекты в диалоговом окне
Settings
, снимите флажок, пока не найдете проекты, которые не имеют правильных настроек (все они имеют правильные настройки).