Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. Мы использовали это для наших проектов:
https://www.codeproject.com/kb/threads/stackwalker.aspx
код немного грязен, по моему скромному мнению, но это работает хорошо. Windows только.
glibc обеспечивает след () функция.
http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
Поскольку Windows проверяет StackWalk64 () API (также в Windows на 32 бита). Для UNIX необходимо использовать собственный способ ОС сделать это, или нейтрализация к следу glibc (), если availabe.
Примечание однако, что взятие Stacktrace в собственном коде редко является хорошей идеей - не потому что это не возможно, но потому что Вы usally пытаетесь достигнуть неправильной вещи.
Большую часть времени люди пытаются вложить stacktrace, скажем, исключительное обстоятельство, как то, когда исключение поймано, утверждать сбои или - худший и самый неправильный из них всех - когда Вы получаете фатальное "исключение" или сигнал как нарушение сегментации.
Рассмотрение последней проблемы, большинство API потребует, чтобы Вы явно выделили память, или может сделать это внутренне. Выполнение так в уязвимом государстве, в котором Ваша программа может в настоящее время быть в, может acutally сделать вещи еще хуже. Например, отчет о катастрофическом отказе (или coredump) не отразит фактическую причину проблемы, но Вашу неудачную попытку обработать его).
я предполагаю, что Вы пробуете к achive, что вещь фатальной обработки ошибок, поскольку большинство людей, кажется, пробует это когда дело доходит до получения stacktrace. Если так, я полагался бы на отладчик (во время разработки) и разрешение процессу coredump в производстве (или мини-дамп на окнах). Вместе с надлежащим управлением символа Вы не должны испытывать никакие затруднения при расчете вскрытия инструкции по порождению.
Нет никакого независимого от платформы способа сделать это.
самая близкая вещь, которую можно сделать, состоит в том, чтобы выполнить код без оптимизации. Тем путем можно присоединить к процессу (использующий отладчик Visual C++ или GDB) и получить применимое отслеживание стека.
Для Windows, CaptureStackBackTrace()
также опция, которая требует, чтобы меньше кода подготовки конца пользователя, чем StackWalk64()
сделало. (Кроме того, для подобного сценария я имел, CaptureStackBackTrace()
закончил тем, что работал лучше (более надежно), чем StackWalk64()
.)
Солярис имеет команда pstack, которая была также скопирована в Linux.
Позвольте мне указать на Вас на свою статью. Это - только несколько строк кода.
, Хотя у меня в настоящее время есть проблемы с x64 реализация этого .
Можно сделать это путем обхода стека назад. В действительности, тем не менее, часто легче добавить идентификатор на стек вызовов в начале каждой функции и вытолкать его в конце, тогда просто обойти ту печать содержания. Это - что-то вроде ЛАВАША, но это работает хорошо и сэкономит Вам время в конце.
Вы должны использовать библиотеку расслабления .
unw_cursor_t cursor; unw_context_t uc;
unw_word_t ip, sp;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
unsigned long a[100];
int ctr = 0;
while (unw_step(&cursor) > 0) {
unw_get_reg(&cursor, UNW_REG_IP, &ip);
unw_get_reg(&cursor, UNW_REG_SP, &sp);
if (ctr >= 10) break;
a[ctr++] = ip;
}
Ваш подход также будет работать нормально, если вы не позвоните от общей библиотеки.
Вы можете использовать команду Addr2line
в Linux, чтобы получить номер / строку / строку источника соответствующего ПК.
Есть backtrace () и backtrace_symbols ():
Из справочной страницы:
#include <execinfo.h>
#include <stdio.h>
...
void* callstack[128];
int i, frames = backtrace(callstack, 128);
char** strs = backtrace_symbols(callstack, frames);
for (i = 0; i < frames; ++i) {
printf("%s\n", strs[i]);
}
free(strs);
...
Один из способов использовать это более удобным способом / ООП - сохранить результат backtrace_symbols () в конструкторе класса исключения. Таким образом, всякий раз, когда вы генерируете исключение такого типа, вы получаете трассировку стека. Затем просто предоставьте функцию для его распечатки. Например:
class MyException : public std::exception {
char ** strs;
MyException( const std::string & message ) {
int i, frames = backtrace(callstack, 128);
strs = backtrace_symbols(callstack, frames);
}
void printStackTrace() {
for (i = 0; i
...
try { throw MyException("Oops!"); } catch ( MyException e ) { e.printStackTrace(); }
Да да!
Примечание: включение флагов оптимизации может сделать итоговую трассировку стека неточной. В идеале эту возможность следует использовать с включенными флагами отладки и выключенными флагами оптимизации.