понедельник, 25 октября 2010 г.

[prog.flame] И за это я тоже не люблю С++

Несколько раз за мою бытность 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 комментария:

  1. оптимизация - по скорости?

    ОтветитьУдалить
  2. > В Release режиме падает. В Debug нет. Если скомпилировать в Release с PDB, то падает. Но студийный отладчик не может показать нормального stack trace. Т.е. даже вообще ничего не показывает, из какого места нашего кода мы оказались в MS-овской DLL-ке – фиг его знает. Как искать причину, ведь явно место сбоя – это уже последствия какой-то наведенной ошибки, а где ее причина… Ничего не понять.

    Майкрософтовские PDB-ки были загружены, или только своя? В смысле, был ли настроен Debug Symbols Server? Если нет то причина отсутствия call-stack-а на 99% в frame pointer ommssion.

    ОтветитьУдалить
  3. Насколько я вспоминаю, подобные проблемы легко находятся AppVerifier-ом (http://technet.microsoft.com/en-us/library/bb457063.aspx)

    ОтветитьУдалить
  4. Вот именно - AppVerifier, Symbol Server и куча всяких вспомогательных технологий. Именно за то что их нужно знать чтобы эффективно работать я ненавижу С++ :)

    ОтветитьУдалить
  5. Спасибо всем ответившим. Сейчас нет времени, ухожу. Продолжу завтра.

    Оптимизация с ключем /O2, вроде бы это по скорости.

    Debug Symbols Server - я сам специально ничего не настраивал.

    ОтветитьУдалить
  6. @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

    ОтветитьУдалить
  7. Первая - расстрел памяти. Вторая - гонка. Третья - нужной дллки не было в path. По-моему так ;)

    ОтветитьУдалить
  8. Может причина не в С++, а в том, что у MS другие приоритеты? И в результате стабильность и преемственность MSVC++ не на первом месте.

    ОтветитьУдалить
  9. @san

    Вообще-то VC для ms критически важная вещь, практически все их продукты реализованы не нем. Ну и судя по 2010 студии не похоже что C++ они забросили.

    ОтветитьУдалить
  10. @Rustam: AFAIK, из последний студий 2008-я была единственной, для которой еще не выпустили service pack. А в идеальное качество таких сложных продуктов я не верю.

    В частности, мой коллега обнаружил, что VC++ 9.0 иногда для DLL-ек и EXE-шников генерирует exp и lib-файлы, даже если оттуда ничего не экспортируется. Оказалось, что это баг компилятора, который был признан MS-ом, но не исправлен (может они его в 2010 пофиксили, но для 2008 исправления я не видел).

    ОтветитьУдалить
  11. @Dmitry Vyukov

    В первом случае очень возможно, что расстрел был. Но, обычно, растрелы проявляются и на других платформах и на других компиляторах.

    Во втором, я все же склонен винить рантайм VC++ 6.0. Все-таки, когда он писался, 4-х процессорных x86 еще не было в природе (ЕМНИП).

    В третьем случае с DLL-ками... У меня была такая мысль, но не было желания копаться. Я ведь cmd.exe из того же FAR-а запускал, так что path и прочие переменные среды должны были унаследоваться. Да и VC++ 9.0 систему манифестов использует, так что там MS-ные DLL-ки должны были системой с учетом манифестов искаться, а не просто по path.

    ОтветитьУдалить
  12. @Евгений Охотников - По расстрелам не все так однозначно. На разных платформах разные memory layout-ы могут прятать подобные ошибки. Короче зависит от того куда попадешь. Где-то приводит к падению, где-то попортит что-нибудь, что не сразу и обнаружишь.

    ОтветитьУдалить
  13. @Sanik: да, так и есть. Но, с другой стороны, не бывает так, чтобы растрел вообще не проявлялся. Хотя, может быть он был где-то в дебрях платформо-зависимого кода.

    ОтветитьУдалить
  14. @Евгений
    Смотрю сейчас через Dependency Walker kernel32 dll в Win 7 показывает Linker Version 9.0. В XP sp3 - 7.1 зато в Win2k sp3 только 5.12.
    Так что сейчас похоже MS компилирует свой самый важный продукт последними выпущенными компиляторами.
    А баги конечно есть, но каких-то запредельных не помню.
    Вообще VC это просто сказка например в сравнении C++ Builder, вот недавно на баг наткнулся компилятор в упор не видел в релизе строк объявленных в заголовочных файлах, ладно я с ассемблером на ты и знаю что этому компилятору нельзя доверять, но все равно прилично времени убил пока не залез в пошаговую ассемблерную отладку.

    ОтветитьУдалить
  15. В целом для того чтобы бороться с Visual C++ настоятельно рекомендую к прочтению вот эту книгу:

    http://www.rsdn.ru/res/book/win32/debugnet.xml

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

    PS Но лично на мою ненависть к С++ эта книга никак не повлияла ;)

    ОтветитьУдалить
  16. /O2 действительно глюковата, на rsdn периодически пробегает, например http://rsdn.ru/forum/tools/342569.flat.aspx

    ОтветитьУдалить
  17. @malgarr

    Угу, у меня сложилось такое впечатление, что на большом количестве inline-функций/методов подглючивает (ведь TCLAP -- это много inline, и в OTL все вообще в одном h-файле).

    ОтветитьУдалить
  18. Я потратился на более современную книжку Advanced Windows Debugging http://www.amazon.com/Advanced-Windows-Debugging-Mario-Hewardt/dp/0321374460
    И, собственно, не пожалел :)
    Правда все меньше приходится под Windows писать.

    ОтветитьУдалить
  19. @Sanik: спасибо за ссылку!

    >Правда все меньше приходится под Windows писать.

    А под что приходится писать? Под Linux?

    ОтветитьУдалить
  20. на моей памяти это так проявляются UB. Более агрессивный оптимизатор нарывается на порядок который проявляет его.

    ну иногда еще проблемы configuration например бинарная либа тащит не совсем тот рантайм или в системе стоит более новый и тп.

    ОтветитьУдалить