Название: Поиск краша Отправлено: Igors от Август 13, 2016, 10:55 Добрый день
Не самый плохой, но достаточно мерзкий случай: вылетает раз в 2-3 дня, когда уже успеваю забыть о нем. Подробности 1) Цитировать Нужен код т.т.п. Увы, это "не транспортабельно"2) Краш происходит всегда в одном месте, на выходе из большого (неск сотен строк) статического метода писаного не мной. Отладчик показывает что летит на деструкторе ~std::string - верить этому необязательно. Ну конечно просмотрел все используемые string, окружил их проверками, но зацепиться за что-то не удалось. Полезные symbolic breakpoint (часто с их помощью удается найти повторное удаление и.т.п.) в этот раз молчат 3) Пытался зациклить ф-цию (с одним и тем же входом и разными) чтобы спровоцировать вылет - нет, и полчаса работает, не летит. Что можно предпринять? Спасибо Название: Re: Поиск краша Отправлено: Bepec от Август 13, 2016, 11:14 Покряхтев, можно натыкать логов много, от слова "дофига". И после очередного краха смотреть по логам где точно произошёл вылет.
Но и это не гарантирует результат, ибо память может портиться где нить в первом часу, а вылет произойдёт во втором :D Название: Re: Поиск краша Отправлено: __Heaven__ от Август 13, 2016, 13:03 У вас поломка, скорее всего далеко не в этом месте. Просто так везёт, что перенаправляет в деструктор строки. Я бы поискал объекты, которые могли бы рядом с этой строкой в стэке стоять. Быть может запись за пределами массива происходит. Вообще, valgrind в помощь.
Название: Re: Поиск краша Отправлено: Racheengel от Август 13, 2016, 13:09 Расход памяти проверить стоит.
У нас была с этим проблема - вылетало раз в 2-3 недели. Выяснилось, что при определенных условиях просто не хватало памяти. Да, еще очень помогают вещи вроде breakpad и crashrpt. https://chromium.googlesource.com/breakpad/breakpad/ http://crashrpt.sourceforge.net/ Название: Re: Поиск краша Отправлено: _Bers от Август 13, 2016, 15:25 Что можно предпринять? 1. отладчики умеют брякаццо на факт изменения значения по адресу. вы знаете, какой объект у вас слетает. значит можете поставить бряку на его изменение. ну а дальше нужно пасти - кто меняет. почему, и на каком основании. то есть смотрим стек вызовов. может быть кто-то из соседнего потока накосячил? 2. техника отладки называется "хвостик". смысл идеи в том, что бы выявить факт пробоя памяти. для этого нужно подвинуть аварийный объект в сторонку: Код: int main() Код: int main() если после этого баг c деструктором перестанет воспроизводится, значит действительно пробой памяти. то есть, кто-то где-то вылез за пределы допустимого диапазона и попал прямо по вашей строке. после вставке бордера, адрес строки смещается, и пробой идет по массиву. строка выживает. но скорее всего краш будет где-то дальше (а может и не будет) 3. дебажный велосипед. в отдельном потоке состояние строки постоянно мониторится. идет проверка: находится ли строка в консистентном состоянии, или уже нет. если уже в неконсистентном состоянии (содержит запрещенные символы, size слишком большой, etc), то исполнение уходит на ветку кода, где стоит обычная бряка. ну а дальше см пункт 1. =========================================== вам в любом случае нужно зафиксировать факт изменения строки, после которого она становится в неконсистентном состоянии. Название: Re: Поиск краша Отправлено: Igors от Август 13, 2016, 15:43 вы знаете, какой объект у вас слетает. К сожалению - пока нетотладчики умеют брякаццо на факт изменения значения по адресу. Пока эти попитки ни к чему не привели - отладчик (gdb) просто вешается намертво ... значит можете поставить бряку на его изменение. смысл идеи в том, что бы выявить факт пробоя памяти. Да, реагирует на изменения в коде. Вот уже неск дней нету после того как я добавил тестовую печать по ifдля этого нужно подвинуть аварийный объект в сторонку: дебажный велосипед. Строка (если это строка, пока не факт) - одна из локальных переменных, которых в ф-ции десятка полтора, многие контейнеры. Т.е. возможно и строка - но не та что в ф-ции, а член класса одного из эл-тов контейнера. в отдельном потоке состояние строки постоянно мониторится. идет проверка: находится ли строка в консистентном состоянии, или уже нет. Название: Re: Поиск краша Отправлено: GreatSnake от Август 13, 2016, 16:00 Довольно-таки странно, что до сих пор не прогнали через valgrind.
Название: Re: Поиск краша Отправлено: Igors от Август 13, 2016, 16:53 Довольно-таки странно, что до сих пор не прогнали через valgrind. Он на OSX не очень - захлебывается при выделениях 500 метров и выше. Да и что там хотим увидеть - "разрушен блок памяти <адрес>"? Это мне и так бы сообщили в gdb, но в данном случае этого нет.Название: Re: Поиск краша Отправлено: _Bers от Август 13, 2016, 17:02 Да и что там хотим увидеть - "разрушен блок памяти <адрес>"? Это мне и так бы сообщили в gdb, но в данном случае этого нет. зная адрес пробитого блока, можно с точностью установить что за объект был подбит. зная этот объект, можно поставить бряку на его изменение. и отловить момент этого изменения. станет видно кто именно постарался. Название: Re: Поиск краша Отправлено: Igors от Август 13, 2016, 17:57 зная адрес пробитого блока, Убрал все тестовые печати - и вылет довольно быстро объявился. Пришел к выводу что да, испорчена строка, локальная переменная в ф-ции. Хмм... ну и как на нее поставить "бряку"? Адреса-то я не имею до входа в ф-цию. Опять налепил тестовых печатей - и опять вылет не появляется...можно с точностью установить что за объект был подбит. зная этот объект, можно поставить бряку на его изменение. и отловить момент этого изменения. станет видно кто именно постарался. Название: Re: Поиск краша Отправлено: Racheengel от Август 13, 2016, 18:36 А дебажный вывод где стоит? до проблемной строки или после?
Если "до" строки воткнуть какой-нибудь безвредный ничонеделающий мусор вместо дебага - эффект тот же? Я бы все же попробовал брекпадом - хотя не знаю, как он на макаке себя вести будет, но на винде нам эта тулза пару раз хорошо помогла. Название: Re: Поиск краша Отправлено: _Bers от Август 13, 2016, 20:07 Убрал все тестовые печати - и вылет довольно быстро объявился. Пришел к выводу что да, испорчена строка, локальная переменная в ф-ции. Хмм... ну и как на нее поставить "бряку"? Адреса-то я не имею до входа в ф-цию. Опять налепил тестовых печатей - и опять вылет не появляется...
[/quote] лично я в вижуал студии сделал бы так: в пошаговой отладки докатился бы до отлаживаемой функции, и брякнулся бы где нибудь в самом начале. далее: Debug -> New Breakpoint -> New Data Breakpoint в открывшемся диалоге вбил адрес охраняемого объекта: &myVariable после чего как только произойдет изменение содержимого адреса отлаживаемого объекта, сработает бряк. насчет вас не знаю. я не телепат. Название: Re: Поиск краша Отправлено: Igors от Август 14, 2016, 10:59 Вот она, сучка
Код Исправил так Код
Название: Re: Поиск краша Отправлено: GreatSnake от Август 14, 2016, 13:46 Вот она, сучка Да уж, такой код иначе и не назовёшь.Название: Re: Поиск краша Отправлено: qate от Август 14, 2016, 18:45 Вот она, сучка И зачем при наличии qt использовать сишные споособы работы ? Название: Re: Поиск краша Отправлено: __Heaven__ от Август 15, 2016, 09:15 Вот она, сучка И зачем при наличии qt использовать сишные споособы работы ? Название: Re: Поиск краша Отправлено: __Heaven__ от Август 15, 2016, 09:20 Довольно-таки странно, что до сих пор не прогнали через valgrind. Он на OSX не очень - захлебывается при выделениях 500 метров и выше. Да и что там хотим увидеть - "разрушен блок памяти <адрес>"? Это мне и так бы сообщили в gdb, но в данном случае этого нет.Название: Re: Поиск краша Отправлено: Igors от Август 15, 2016, 09:52 И зачем при наличии qt использовать сишные споособы работы ? Да уж, такой код иначе и не назовёшь. Ну как сказать.. А как бы написал я при отсутствии Qt? Наверное тоже бы читал ifstream в буфер, тоже бы отсекал вындозный конец строки - в общем принципиально ничем не лучшеИмхо, пускай захлёбывается. Уж лучше он будет сутки искать ошибку, чем это буду делать я трое суток. Я это время потрачу на что-нибудь другое. Ну в данном случае он бы ничего не нашел - утечек нет, куча не бита. В свое время мой интерес к valgrind быстро охладел когда я познакомился с гораздо более приятными "Instruments" (Memory Leak и др)Название: Re: Поиск краша Отправлено: __Heaven__ от Август 15, 2016, 10:27 Есть экспериментальный инструмент SGCheck, который включается опцией --tool=exp-sgcheck, возможно, он бы вам помог.
А тут пример того, как безопасно можно было бы прочитать строку http://en.cppreference.com/w/cpp/string/basic_string/getline Название: Re: Поиск краша Отправлено: Igors от Август 15, 2016, 10:58 А тут пример того, как безопасно можно было бы прочитать строку http://en.cppreference.com/w/cpp/string/basic_string/getline Конечно прочитать в std::string было бы аккуратнее. Вообще осуждать др программиста писавшего этот код легко. Но при этом не стоит забывать - "плохой" код реализует не слабый кусок ф-ционала. В аттаче пример файла что он читает. И у меня как-то не возникает желания переписать это чтение с нуля :) Ну заменю я массив на контейнер и strlen/strtok на что-то получше - так это пол-процента от всей работы (такова обычная цена умничания :))Название: Re: Поиск краша Отправлено: __Heaven__ от Август 15, 2016, 11:46 Так ведь, не с нуля. Можно написать тестик и потихонечку выделять отдельные операции в методы и постепенно заменять их на c++ функционал. Вы, скорее всего, снова наступите на эти грабли и суммарное время потраченное на поиск ошибок превысит время, которое бы ушло на исправление этого участка кода.
Название: Re: Поиск краша Отправлено: Igors от Август 15, 2016, 11:53 Так ведь, не с нуля. Можно написать тестик и потихонечку выделять отдельные операции в методы и постепенно заменять их на c++ функционал. Вы, скорее всего, снова наступите на эти грабли и суммарное время потраченное на поиск ошибок превысит время, которое бы ушло на исправление этого участка кода. Да, если бы найти не удалось - пришлось бы рефакторить, но это тоже совсем не дешево. A "потихонечку" (постепенно улучшать) не всегда есть возможность. Название: Re: Поиск краша Отправлено: Авварон от Август 23, 2016, 18:41 А вас не смущает тройной (после фикса двойной) вызов strlen?
|