Несколько раз за мою бытность C++ником происходили случаи, когда мои C++ные программы падали, а я не мог объяснить причины этого. Причем всегда это было связано с Visual C++ компиляторами. Вспоминаются следующие случаи.
В первый раз это было где-то в 1998-м, когда я под VC++ 4.2 тестировал свою собственную объектную СУБД. Сервер БД падал, когда к нему несколько раз подключались, активно работали, а потом отключались клиенты. Падал в достаточно произвольные моменты. В принципе, я смог выстроить цепочку действий, которая гарантировано ломала сервер, но произойти это могло как через 5 минут, так и через 15 минут работы.
Долго я тогда искал причины проблемы, наверное дня три сидел за машиной с утра до вечера. И ничего не мог найти, да и тот же самый сервер под OS/2 работал вообще без проблем. В результате все закончилось тем, что в одном из мест программы я заменил один свой самописный контейнер на другой – программа падать перестала.
Второй раз дело было году в 2003. Поставили мы тогда написанную под заказ систему на четырехпроцессорную машину заказчика. А она стала периодически зависать. Опять же в произвольные моменты времени, но в итоге зависала.
Пользовались мы тогда VC++ 6.0. Пару дней я убил чтобы проблему найти, благо машина заказчика тогда у нас стояла. Ничего не нашел. Просто перекомпилировал приложение VC++ 7.1 – зависать перестало. И под MinGW так же не зависало. Такой эффект только под VC++ 6.0 проявлялся.
С VC++ 9.0 (это который из VS2008) недавно прикол был. Компилирую маленькую утилитку, в которой библиотека TCLAP используется. Запускаю без аргументов (чтобы выдачу справки спровоцировать) из FAR-а или Cygwin-овского bash-а – падает. Если тоже самое из cmd.exe – не падает. На машине разработчика вообще не падает. Пытаешься отлаживаться – отладчик ничего путного не говорит. Перешли на новую версию TCLAP, таких приколов больше не наблюдается. Если же компилироваться VC++ 7.1, то вообще никогда не падает.
А вот последний случай произошел на прошлой неделе. Потребовалось доработать приложение, которое некоторое время назад было переведено с VC++ 7.1 на VC++ 9.0. Доработал. Стало эпизодически падать.
В Release режиме падает. В Debug нет. Если скомпилировать в Release с PDB, то падает. Но студийный отладчик не может показать нормального stack trace. Т.е. даже вообще ничего не показывает, из какого места нашего кода мы оказались в MS-овской DLL-ке – фиг его знает. Как искать причину, ведь явно место сбоя – это уже последствия какой-то наведенной ошибки, а где ее причина… Ничего не понять.
Опыт подсказывает, что вероятность моей собственной ошибки гораздо больше, чем ошибки где-то в компиляторе. Но опыта не хватает, чтобы проблему выявить. Проект-то очень не маленький, плюс сторонних библиотек в нем достаточно (одни только ACE с POCO и OTL чего стоят). Тем более, что под VC++ 7.1 все работает как часы. И так хочется верить, что это глючит оптимизатор в проклятой мастдаевской мелкомягкой поделке! :)))
Блин, не люблю я C++ за такие вещи. Убиваешь время на пустом месте. Жалко, что я в свое время поиск замены C++ так и не закончил. Хочется временами чего-нибудь железобетонного, чтобы не то что ногу отстрелить, чтобы даже прицелиться в нее нельзя было :)))
22 комментария:
оптимизация - по скорости?
> В Release режиме падает. В Debug нет. Если скомпилировать в Release с PDB, то падает. Но студийный отладчик не может показать нормального stack trace. Т.е. даже вообще ничего не показывает, из какого места нашего кода мы оказались в MS-овской DLL-ке – фиг его знает. Как искать причину, ведь явно место сбоя – это уже последствия какой-то наведенной ошибки, а где ее причина… Ничего не понять.
Майкрософтовские PDB-ки были загружены, или только своя? В смысле, был ли настроен Debug Symbols Server? Если нет то причина отсутствия call-stack-а на 99% в frame pointer ommssion.
Насколько я вспоминаю, подобные проблемы легко находятся AppVerifier-ом (http://technet.microsoft.com/en-us/library/bb457063.aspx)
Вот именно - AppVerifier, Symbol Server и куча всяких вспомогательных технологий. Именно за то что их нужно знать чтобы эффективно работать я ненавижу С++ :)
Спасибо всем ответившим. Сейчас нет времени, ухожу. Продолжу завтра.
Оптимизация с ключем /O2, вроде бы это по скорости.
Debug Symbols Server - я сам специально ничего не настраивал.
@Left А Вы не подскажите мне в какой области инженерии ПО не надо знать инструментарий и при этом быть продуктивным? Я например полностью разделяю следующее утверждение "Tools amplify your talent. The better your tools, and the better you know how to use them, the more productive you can be." из http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X
Первая - расстрел памяти. Вторая - гонка. Третья - нужной дллки не было в path. По-моему так ;)
Может причина не в С++, а в том, что у MS другие приоритеты? И в результате стабильность и преемственность MSVC++ не на первом месте.
@san
Вообще-то VC для ms критически важная вещь, практически все их продукты реализованы не нем. Ну и судя по 2010 студии не похоже что C++ они забросили.
@Rustam: AFAIK, из последний студий 2008-я была единственной, для которой еще не выпустили service pack. А в идеальное качество таких сложных продуктов я не верю.
В частности, мой коллега обнаружил, что VC++ 9.0 иногда для DLL-ек и EXE-шников генерирует exp и lib-файлы, даже если оттуда ничего не экспортируется. Оказалось, что это баг компилятора, который был признан MS-ом, но не исправлен (может они его в 2010 пофиксили, но для 2008 исправления я не видел).
@Dmitry Vyukov
В первом случае очень возможно, что расстрел был. Но, обычно, растрелы проявляются и на других платформах и на других компиляторах.
Во втором, я все же склонен винить рантайм VC++ 6.0. Все-таки, когда он писался, 4-х процессорных x86 еще не было в природе (ЕМНИП).
В третьем случае с DLL-ками... У меня была такая мысль, но не было желания копаться. Я ведь cmd.exe из того же FAR-а запускал, так что path и прочие переменные среды должны были унаследоваться. Да и VC++ 9.0 систему манифестов использует, так что там MS-ные DLL-ки должны были системой с учетом манифестов искаться, а не просто по path.
@Евгений Охотников - По расстрелам не все так однозначно. На разных платформах разные memory layout-ы могут прятать подобные ошибки. Короче зависит от того куда попадешь. Где-то приводит к падению, где-то попортит что-нибудь, что не сразу и обнаружишь.
@Sanik: да, так и есть. Но, с другой стороны, не бывает так, чтобы растрел вообще не проявлялся. Хотя, может быть он был где-то в дебрях платформо-зависимого кода.
@Евгений
Смотрю сейчас через Dependency Walker kernel32 dll в Win 7 показывает Linker Version 9.0. В XP sp3 - 7.1 зато в Win2k sp3 только 5.12.
Так что сейчас похоже MS компилирует свой самый важный продукт последними выпущенными компиляторами.
А баги конечно есть, но каких-то запредельных не помню.
Вообще VC это просто сказка например в сравнении C++ Builder, вот недавно на баг наткнулся компилятор в упор не видел в релизе строк объявленных в заголовочных файлах, ладно я с ассемблером на ты и знаю что этому компилятору нельзя доверять, но все равно прилично времени убил пока не залез в пошаговую ассемблерную отладку.
В целом для того чтобы бороться с Visual C++ настоятельно рекомендую к прочтению вот эту книгу:
http://www.rsdn.ru/res/book/win32/debugnet.xml
Там и про то зачем нужны дебажные символы не только для своей Dll, и про многое-многое другое.
PS Но лично на мою ненависть к С++ эта книга никак не повлияла ;)
@Left: спасибо за ссылку.
/O2 действительно глюковата, на rsdn периодически пробегает, например http://rsdn.ru/forum/tools/342569.flat.aspx
@malgarr
Угу, у меня сложилось такое впечатление, что на большом количестве inline-функций/методов подглючивает (ведь TCLAP -- это много inline, и в OTL все вообще в одном h-файле).
Я потратился на более современную книжку Advanced Windows Debugging http://www.amazon.com/Advanced-Windows-Debugging-Mario-Hewardt/dp/0321374460
И, собственно, не пожалел :)
Правда все меньше приходится под Windows писать.
@Sanik: спасибо за ссылку!
>Правда все меньше приходится под Windows писать.
А под что приходится писать? Под Linux?
под него, родимого :)
на моей памяти это так проявляются UB. Более агрессивный оптимизатор нарывается на порядок который проявляет его.
ну иногда еще проблемы configuration например бинарная либа тащит не совсем тот рантайм или в системе стоит более новый и тп.
Отправить комментарий