LINUX.ORG.RU

как отлавливать серьезные траблы со стеком и кучей

поделитесь своими методиками в ситуации когда valgrind ничего не находит.

а почему Вы решили что именно стек и куча виноваты?

shty ★★★★★
()

Медитация над кодом, старый добрый метод половинного деления, вывод максимально подробной информации в процессе выполния.

AIv ★★★★★
()
Ответ на: комментарий от shty

если бы я знал кто виноват - уже б пофиксил. отладчик показывает что вызов malloc() изменяет пользовательские переменные и адрес возврата из ф-и.

cvv ★★★★★
() автор топика

Бисекция (по VCS или по коду).

tailgunner ★★★★★
()
Ответ на: комментарий от cvv

если бы я знал кто виноват - уже б пофиксил

ну так локализация виноватого - это ж первая задача :)

берёте в руки дебаггер (возможно какой-нибудь stackwalker) и вперде, смотреть где ноги начинают ещё не отламываться но уже похрустывать

и да, симптомы похожи на встречу shallow copy и указателей :)

shty ★★★★★
()
Ответ на: комментарий от mashina

я запускаю валгринд следующим образом:

valgrind --suppressions=cfifo/tests/valgrind-python-2.5.supp \
    --log-file=test.valgrind --leak-check=full --show-reachable=yes \
    -v --malloc-fill=55 --free-fill=AA --read-var-info=yes \
    python viz_3d/test_viz_3d.py

Мне только что посоветовали использовать патченый валгринд с http://valgrind.org/downloads/variants.html?njn

cvv ★★★★★
() автор топика
Ответ на: комментарий от AIv

однопоточное, стабильно и даже воспроизводятся на винде. Основная проблема что слишком далеко программа заходит прежде чем ошибка проявляется.

cvv ★★★★★
() автор топика
Ответ на: memory debugger от sieq

Ревизия кода, хоть и сложный шаг, но, кроме исправления ошибок, позволяет улучшить внутреннюю структуру приложения. Порой это позволяет в будущем сэкономить даже больше времени на разработке остального функционала, чем было затрачено на саму ревизию.

trex6 ★★★★★
()
Ответ на: комментарий от AIv

Медитация над кодом, старый добрый метод половинного деления, вывод максимально подробной информации в процессе выполния.

Подписываюсь подо всем.

Pavval ★★★★★
()
Ответ на: комментарий от cvv

Однопоточное - уже проще. И какие проблемы? Собираетесь с опцией -g, запускаетесь под gdb, падаете, смотрите стек (набрав bt), а дальше втыкаете вывод отладочной информации по всем имеющим отношение к упадению переменным - кто их поменял, почему поменял, кто поменял того кто поменял и тд. Довольно быстро расковыривается.

AIv ★★★★★
()
Ответ на: комментарий от AIv

Хорошо, вот смотри:

есть у меня переменная state которая изменяется «загадочным» образом в неположеном месте. Я в дебагере ставлю на нее watchpoint и обнаруживаю что эта переменная была изменена вызовом malloc(). насколько я понимаю это связано с тем что какойто код попортил структуры используемые malloc(). но так как malloc() библиотечная ф-я то я теряюсь в догадках как поставить watchpoint на используемые им структуры чтобы отловить изменяющий их код. Хуже всего что нет никакой гарантии что эти изменения вызывает именно мой код, а не чужой, так как я делаю часть нехилой аппликухи.

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

Отлаживать программы отладчиками - самое последнее дело. Я ими последной раз пользовался лет 10 назад и больше нет потребности. И без них всё отлаживается прекрасно и гораздо лучше.

anonymous
()
Ответ на: комментарий от cvv

Посмотри на аргументы этого маллока? И на тех, кто их формирует.

Вообще тут чего то не то. Переменная стековая? watchpoint конечно круто, но куда надежней (мб я конечно gdb пользоваться не уменю) поставить тупой вывод (в лог, на stdout, на stderr) этой самой переменной до вызова маллока и после. Я не очень понимаю, как непосредственно вызов маллока может засохатить стек, если тока кадр стека не был разрушен до вызова. А вот при формировании аргументов такое возможно.

AIv ★★★★★
()
Ответ на: комментарий от cvv

Еще хороший рецепт - попытаться вычленить минимальный кусок кода приводящего к ошибке. Выкинуть все, оставить только то, что валится. Это должно быть что то простое, иначе бы ошибка не вопроизводилась с такой стабильностью на разных системах. И то что валгринд ничего не говорит... очень странно, он придирчивая зараза.

AIv ★★★★★
()
Ответ на: комментарий от cvv

> есть у меня переменная state которая изменяется «загадочным» образом в неположеном месте. Я в дебагере ставлю на нее watchpoint и обнаруживаю что эта переменная была изменена вызовом malloc(). насколько я понимаю это связано с тем что какойто код попортил структуры используемые malloc(). но так как malloc() библиотечная ф-я то я теряюсь в догадках как поставить watchpoint на используемые им структуры чтобы отловить изменяющий их код. Хуже всего что нет никакой гарантии что эти изменения вызывает именно мой код, а не чужой, так как я делаю часть нехилой аппликухи.

А структура, содержащая эту переменную, не была случайно удалена до вызова malloc?

dave ★★★★★
()
Ответ на: комментарий от dave

валгринд бы это засек сразу. И потом ошибка бы тогда не воспроизводилась стабильно на разных ОС, а была бы плавающей. Распределение памяти вещь случайная и когда там пеерекроется освожденный участок одному Бэббиджу известно;-)

AIv ★★★★★
()
Ответ на: комментарий от cvv

Я в дебагере ставлю на нее watchpoint и обнаруживаю что эта переменная была изменена вызовом malloc(). насколько я понимаю это связано с тем что какойто код попортил структуры используемые malloc()

Есть много сценариев. Например, структура изначальна могла получить неправильный адрес (залезла на структуры heap'а).

mashina ★★★★★
()
Ответ на: комментарий от AIv

> Посмотри на аргументы этого маллока? И на тех, кто их формирует.

ну у malloc() только один аргумент и даже если в нем ошибится то ничего фатального быть не должно, это ведь не realloc() или free().

Вообще тут чего то не то.

однозначно

Переменная стековая?

нет, переменная в куче

А вот при формировании аргументов такое возможно.

ну это если бага в gcc ... или я неправ?

cvv ★★★★★
() автор топика
Ответ на: комментарий от AIv

ммм. в текущей ситуации затрудняюсь сообразить как это можно сделать. слишком много независимых переменных.

cvv ★★★★★
() автор топика
Ответ на: комментарий от vaulter

мне уже предлагали, но я сомневаюсь в его полезности в ситуации когда безсилен valgrind

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

>> А вот при формировании аргументов такое возможно.

ну это если бага в gcc ... или я неправ?

Не прав;-) Напр. выражение вида int p[10]; p[-1]=... радостно запорет тебе стек (ну или поля структуры лежащие до него).

AIv ★★★★★
()
Ответ на: комментарий от AIv

так мы ж о формировании аргументов для передачи в ф-ю. а это выражение вне всякого сомнения запорет стек. но и valgrind кажется без проблем такое отлавливает.

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

Это был пример. Вполне возможно сформировать аргумент, сносящий что то рядом, мне помнится такое удавалось. А на каком то хитром выражении валгринд может и не сработать - у себя ж в данных гадишь, откуда он знает что это баг а не фича?

Симптоматика странная, если б это была классическая ошибка с адресной арифметикой то и валгринд бы чирикнул, и главное ошибка была бы плавающей. Ну конечно гипотетически может быть какой то странный алиасинг, когда у тебя одинаковые смещения в итоге получаются, но я себе такого представить не могу.

AIv ★★★★★
()
Ответ на: комментарий от cvv

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

AIv ★★★★★
()
Ответ на: комментарий от cvv

ты намекаеш на багу а glibc?

Багов в malloc() скорее всего нет, вероятность поймать такую очень низкая. Так же не стоит расчитывать на баги в gcc по аналогичной причине, если конечно не используешь совсем новый gcc из транка или тестовую версию.

Намекаю на stack smash или что-то в подобном роде. Например, выделил память

char *ptr = malloc(...);

Далее произошёл stack smash и уже неправильное значение ptr записываешь в постоянную структуру. Или такое могло случиться сразу на объекте.

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

В википедии показан один из возможных примеров когда valgrind не увидит проблемы.

Нужно следить за указателем с самого начала его создания, от malloc()'а.

mashina ★★★★★
()

Появилась идея все malloc и free подменить на mmap/munmap. думаю код обвалится раньше или в другом месте.

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

кстати как valgring будет понимать мамять выделенну mmap?

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

Вероятность всегда есть. Electric fence насколько я помню, заменяет libc'шные *alloc. Если в вашем случае корраптятся структуры кучи, это может помочь уронить с SIGSEGV программу раньше, чем сейчас. В идеальном случае в момент повреждения памяти.

С этой целью может помочь любая альтернативная реализация malloc().

vaulter
()
Ответ на: комментарий от cvv

malloc() и так выделает память через mmap() если кусок достаточно большой (по умлочанию 128кб). Порог можно поменять через mallopt(). Но в этом нет особого смысла.

mashina ★★★★★
()
Ответ на: комментарий от vaulter

профайлер кучи у valgrind'а делает абсолютно тоже самое. И любой другой профайлер аналогично, иначе просто сделать трудно.

mashina ★★★★★
()

PROGRESS

покачто результат дало mmap()+mprotect(). улетаем в сегфолт существенно раньше чем изначально.

cvv ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.