Когда использовать язык ассемблера для отладки программы на языке c / c ++? - PullRequest
3 голосов
/ 07 июня 2009

Когда использовать сборку для отладки программы на языке c / c ++?

Помогает ли научиться некоторой сборке для отладки программ?

Ответы [ 12 ]

5 голосов
/ 07 июня 2009

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

Кроме того, по моему опыту (в основном в отладке ядра) отладчики были относительно плохи в работе с оптимизированным кодом. Они получают такие вещи, как параметры / и т.д. неверны, и действительно говорят, что происходит, мне нужно посмотреть diassembly.

Если я могу воспроизвести проблему надежно / легко, она не будет столь полезной разобраться с разборкой, потому что я получу больше информации от простого шага через программу. С другой стороны, добраться до точки, где вы можете Воспроизвести проблему, как правило, более чем на полпути к ее решению.

3 голосов
/ 07 июня 2009

Я не могу сказать вам "Когда", но иногда вы можете иметь странное поведение C / C ++, и вы действительно не понимаете, что происходит ... Просто посмотрите на код asm, он никогда не предаст вас.

Но здесь я постоянно проверяю код ASM моих программ на Си ... для целей оптимизации, любопытства и обучения.

Обязательно изучите язык ассемблера x86!

2 голосов
/ 07 июня 2009

Я определенно вернулся к чтению сборки несколько раз. GCC делает это довольно удобным.

Один хороший пример - тема одного из моих вопросов . GCC изменил поведение между 2.95 и 3.4.3, и переход к сборке в функции подозрения объяснил, почему моя программа вылетала.

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

Другой случай, для которого я недавно использовал ассемблер, - это проверка того, что мои переменные 'volatile' действительно обрабатываются как volatile. Оказывается, что почти все компиляторы иногда ошибаются, поэтому я начал проверять вывод конкретных случаев, чтобы убедиться, что сборка действительно ссылается на область памяти, а не на какой-либо регистр.

2 голосов
/ 07 июня 2009

Полагаю, вы спрашиваете, когда использовать дизассемблирование, когда вы хотите отладить написанный на C / C ++ код.

Будут случаи, когда вы подозреваете, что компилятор не сгенерировал код, как вы бы этого хотели. Как правило, когда оптимизированная версия исполняемого файла работает неправильно, но неоптимизированная форма работает хорошо. Затем вы захотите проверить разборку, чтобы увидеть, какая оптимизация изменила поведение.

Другой случай - когда вы хотите понять поведение исполняемого файла, но у вас нет исходного кода для начала - это называется обратным инжинирингом. У вас нет вариантов, кроме как работать с разборкой исполняемого файла.

Справочник по вики о инструментах разборки и анализа для понимания инструментов и начала изучения наиболее подходящих для вашей среды.

2 голосов
/ 07 июня 2009

Если вы не подозреваете, компилятор, я бы не пошел на низком уровне для отладки. Лучше всего отлаживать на том же уровне абстракции, на котором вы выражаете свое намерение в алгоритме.

Если вы пишете код на C / C ++, используйте хороший отладчик C / C ++.

1 голос
/ 01 августа 2009

Я думаю, вам нужно будет изучить ассемблер когда-нибудь. Знание сборки - единственный выход, если ошибка воспроизводима только в сборке релиза или при отладке сторонней библиотеки, в которой у вас нет исходного кода. Есть больше причин изучать сборку, чем нет.

Возможно, вы также захотите взглянуть на мои последние статьи об отладке в сборке - http://mohit.io/blog/assembly-and-the-art-of-debugging/

Обновление -> Если вы хотите изменить поведение вашего кода во время выполнения без перекомпиляции, тогда изучение ассемблера обязательно. Посмотрите на http://mohit.io/blog/debugging-modifying-code-at-runtime/

1 голос
/ 07 июня 2009

В некоторых случаях у вас нет выбора, кроме как вернуться к ассемблеру. Если ваша система дает сбой, и все, что у вас есть, это дамп ядра или трассировка стека с небольшим количеством символов, то если вы посмотрите на исходный код высокого уровня, это не даст вам слишком далеко

1 голос
/ 07 июня 2009

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

Например

/* global */
int x = 1;

void *myFunc() {
    /* do something productive */
    x = 0;
    return NULL;
} 

int main() {
    thread_create(myFunc);

    while(x) continue;

    exit(1);
}

При определенных оптимизациях while(x) continue; становится jmp 0xDEADBEEF (где 0xDEADBEEF - инструкция jmp). Вы можете видеть это в сборке и знать, чтобы изменить x на volatile.

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

1 голос
/ 07 июня 2009

Это может помочь с некоторыми из продвинутых вещей, и это всегда помогает понять, что происходит "под капотом". Но если вы все равно не делаете ассемблерное кодирование (и если бы вы это знали, вы бы знали ассемблер), отладка с ассемблером, вероятно, излишня. Ошибки, вероятно, будут непосредственно в вашем коде, а не в переводе между вашим кодом и сборкой.

0 голосов
/ 01 августа 2009

Это полезно для отладки оптимизированных сборок релиза; в частности, когда клиент отправляет вам мини-дамп из вашего приложения в поле. В этих случаях многие отладчики довольно слабы для отслеживания локальных переменных, и вам приходится вылавливать их из стека (или регистров) вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...