Про отладку в Win32/Visual Studio 2010

Вот есть программа, один и тот же бинарник, релизная сборка. У пользователя - падает при некоторых входных данных. Проверяю у себя:

  • Запускаю просто бинарь, подаю проблемные данные - падает.
  • Запускаю тот же самый бинарь (релизный, без пересборки) из Visual Studio (2010) - работает.

Падает оно в buffer overrun, в одном и том же месте (внутри ntdll, а туда попадает из malloc, которому дали неверные данные в результате более раннего overrun).

Вопрос: как такое может быть? Visual Studio при отладке релизных бинарников подпихивает другие DLL? Или вообще что?

Update подниму из комментов эту вот ссылку: http://blogs.msdn.com/b/oldnewthing/archive/2013/01/03/10381959.aspx

В моем случае это оказалось ОНО. Т.е. _NO_DEBUG_HEAP - и сразу счастье. В том смысле, что ошибка появилась и под отладчиком.

Comments

debugging heap, если я ничего не путаю, отличается от просто хипа.

Дык все релизное.
И DLL-ки (MSVC runtime) подставляются - релизные, msvcr100, а не msvcr100d

О!
If you are using Visual Studio, you can set the _NO_DEBUG_HEAP environment variable to 1.

Спасибо. Буду пробовать.

Да, это ОНО.

Спасибо.

Может VS выключает virtual address space randomization, стэк/куча оказываются в определённых местах и всё случайно срастается. В линуксах это можно сделать снаружи через personality(2). Возможно в винде есть что-то похожее.

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

У меня один буфер (выделенный через просто malloc) затирал кусок следующего буфера - и все портилось.
Если бы была рандомизация (без VS) - это срабатывало бы через раз, но без VS - все воспроизводимо падало, каждый раз одинаково.

А с VS - похоже что второй буфер (крохотный, 16 байт) выделяется где-то еще и потому - не затирается.

VS подсовывает свой malloc() с блек-джекомдебагом?

Ну ломается то все в msvcr100.dll - которая, по идее, одна и та же в обоих случаях (дебажная называется msvcr100d)

Т.е. гипотеза у меня такая: в одном случае берутся dll-ки из system32, в другом - те, которые с программой (и по размеру они разные и вообще их у меня на машине 31 штука).

Но вот тщательное конструирование каталога в котором были бы и проблемный бинарник и этот самый рантайм - делу не помогло, найти вариант при котором оно не падало бы без студии - не удалось.

Потому и спрашиваю, собственно.

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

Можно запускать, ждать пока упадет, а потом подключать отладчик же.

Ну так я так и делал - и источник проблемы узнал и починил.

Остается вопрос - отчего запущенное из DevEnv - не падает

Ну а сама-то ntdll одинаковая? Версии винды, сервиспаки, отладочные данные для неё и т.д.

Это одна и та же винда. Т.е. я надеюсь что одинаковая.

Есть такой товарищ, который в подобные темы по долгу службы закапывается в Мракософте, может быть спишитесь?
http://blogs.technet.com/b/not-a-kernel-guy/

Пахунов уже больше года работает в гугле

Неоднократно такое наблюдалось, когда релиз из под студии работает а так падает. Один из вариантов, что все-таки адреса могут по разному ложится, другой - может есть все-таки какой-то переменный фактор, типа где-то openmp цикл или еще что-то что может давать некую недетерменированность в последовательности вызовов.

Кстати мы используем три конфигурации: debug, release и gold. gold - это обычный release, а в release еще включен debug info и есть логгирование assert-ов, с этим можно посмотреть стек, критические ассерты, а иногда и некоторые переменные. В таком случае release почти всегда повторяет поведение gold-а.

Хм.
У нас release - это без ассертов, но с дебаг инфо в пдб . Кастомерам оно идёт без пдб, но отладочная информация релизов всегда хранится. Таким образом если где-то что-то сыпется, то можно всегда достать старый релиз и на нём воспроизвести с дебагером и поотлаживать.

Да, это правильная мысля - хранить .pdb

А крэшдампы виндовые - вы собираете и анализируете?

А ещё никто не присылал ;)
Чаще говорят, как воспроизводить. И бывает, что хорошо вопсроизводится только на том билде, который отрепортили, но бага есть и в других, только лучше спрятана. Поэтому проверяем всегда, даже если есть похожий починенный баг репорт.