backtracing deeper
Sep. 12th, 2005 03:27 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
собственно, продолжение http://www.livejournal.com/users/airmax/60695.html#cutid1
во-первых, никто не отменял чтение документации перед употреблением системных функций :
вызывайте free на результат backtrace_symbols
во-вторых, хотя контекст вызова bt и понятен по первому элементу стека, всё-таки удобней передавать ей имя блока для вывода в лог
void bt(char* fooname)
{
int c, i;
void *addresses[10];
char **strings;
c = backtrace(addresses, 10) ;
strings = backtrace_symbols(addresses,c);
err_report(errfd, "backtrace of %s returned: %d\n", fooname, c);
for(i = 0; i < c; i++) {
err_report(errfd, "[bt] %d: %X %s\n", i, (int)addresses[i], strings[i]);
free(strings);
}
}
в-третьих, для нормального употребления, рекомендуется компилировать со следующими ключами:
g++ -g -fPIC -O -rdynamic
и кормить порожденный лог утилитам c++filt или addr2line.
первая делает demangle имени C++ функции/метода.
вторая берет адрес в бинарнике и пытается получить по нему имя файла и номер строки
собственно, ловушка на слонопотама теперь выглядит так (tee и ключ -f добавлены чтобы и на терминале любоваться):
где /home/responder/logs/errors - имя файла, в который фигачит err_repost,
responder - имя бинарника, который падает, гад.
backtrace.log - имя лога, в который сваливается только
если выводить также и имя функции, а не только номер строки - добавляете -f к addr2line - но при этом вывод сильно разъезжается если используются С++-ные std классы =)
поэтому, далее - кастуем фильтр, сворачивающий шаблоны STL до удобоваримых std::string, std::vector и т.п.
Качаем:
wget "http://www.downloadcounter.com/cgi-bin/download.pl?username=leor&account=5" | tar -xf gstlfilt.tar gSTLFilt.pl
Используем:
А теперь, внимание, вопрос: кто мне сможет объяснить, почему когда perl gSTLFilt.pl подается на вход строчка
"CDbImpl::SelectMap(char const* (*) [2], ...", выдается "CDbImpl::SelectMap(char const errors.log backtrace.log gSTLFilt.pl ..."
То есть, какое-то нездоровое поведение перла, видимо - первый "*" разворачивает в имена всех файлов в текущем каталоге. Как этого избежать?
Update: все неправы, ха-ха-ха. Точнее, более всего прав Бреслав - двойные кавычки нужно убрать. Только нужно не заменить их все на одинарные - это тут просто не прокатит, а перед `addr2line, и, соответственно, после gSTLFilt.pl ` - убрать \".
во-первых, никто не отменял чтение документации перед употреблением системных функций :
вызывайте free на результат backtrace_symbols
во-вторых, хотя контекст вызова bt и понятен по первому элементу стека, всё-таки удобней передавать ей имя блока для вывода в лог
void bt(char* fooname)
{
int c, i;
void *addresses[10];
char **strings;
c = backtrace(addresses, 10) ;
strings = backtrace_symbols(addresses,c);
err_report(errfd, "backtrace of %s returned: %d\n", fooname, c);
for(i = 0; i < c; i++) {
err_report(errfd, "[bt] %d: %X %s\n", i, (int)addresses[i], strings[i]);
free(strings);
}
}
в-третьих, для нормального употребления, рекомендуется компилировать со следующими ключами:
g++ -g -fPIC -O -rdynamic
и кормить порожденный лог утилитам c++filt или addr2line.
первая делает demangle имени C++ функции/метода.
вторая берет адрес в бинарнике и пытается получить по нему имя файла и номер строки
собственно, ловушка на слонопотама теперь выглядит так (tee и ключ -f добавлены чтобы и на терминале любоваться):
tail -f /home/responder/logs/errors | grep "\[bt\]" | awk '{ print "echo \"",$1,$2,$3,"\" `addr2line -C -s -e responder "$4"` \"",$5,$6,$7,"\""}' | sh | tee -a backtrace.log
где /home/responder/logs/errors - имя файла, в который фигачит err_repost,
responder - имя бинарника, который падает, гад.
backtrace.log - имя лога, в который сваливается только
если выводить также и имя функции, а не только номер строки - добавляете -f к addr2line - но при этом вывод сильно разъезжается если используются С++-ные std классы =)
поэтому, далее - кастуем фильтр, сворачивающий шаблоны STL до удобоваримых std::string, std::vector
Качаем:
wget "http://www.downloadcounter.com/cgi-bin/download.pl?username=leor&account=5" | tar -xf gstlfilt.tar gSTLFilt.pl
Используем:
tail -f /home/responder/logs/errors | grep "\[bt\]" | awk '{ print "echo \"",$1,$2,$3,"\" `addr2line -C -s -e responder "$4" | perl gSTLFilt.pl ` \"",$5,$6,$7,"\""}' | sh | tee -a backtrace.log
А теперь, внимание, вопрос: кто мне сможет объяснить, почему когда perl gSTLFilt.pl подается на вход строчка
"CDbImpl::SelectMap(char const* (*) [2], ...", выдается "CDbImpl::SelectMap(char const errors.log backtrace.log gSTLFilt.pl ..."
То есть, какое-то нездоровое поведение перла, видимо - первый "*" разворачивает в имена всех файлов в текущем каталоге. Как этого избежать?
Update: все неправы, ха-ха-ха. Точнее, более всего прав Бреслав - двойные кавычки нужно убрать. Только нужно не заменить их все на одинарные - это тут просто не прокатит, а перед `addr2line, и, соответственно, после gSTLFilt.pl ` - убрать \".