나는이 문제를 가지고 해결책을 찾기 위해 사냥을했지만, 아무것도 찾지 못했습니다. 귀하의 게시물에 OSX 태그를 추가 했으므로이 플랫폼이 작동하기를 원합니다. 글쎄 OSX에는 addr2line이 없다. 적어도 OSX 버전 10.8/10.9에는 없다. 나는 (다양한 소스에서 조각을 사용하여) 아래의 코드를 함께 넣어, 그것은 (이것은 예외 처리기입니다 상단 두 개의 프레임을 원하는 경우, 당신은이를 건너 뛸 수 포함)과 같이 백 트레이스를 생성
Caught SIGBUG: Bus error (bad memory access)
0 MyGame 0x342878 ExceptionHandler::PrintStackTrace() (in MyGame) (MacOSXEngine.cpp:89)
1 MyGame 0x342c4e ExceptionHandler::Handler(int, __siginfo*, void*) (in MyGame) (MacOSXEngine.cpp:232)
2 libsystem_platform.dylib 0x92beedeb 0x92beedeb
3 ??? 0xffffffff 0 + 4294967295
4 MyGame 0x48ae93 GlfwGraphicsSystem::Initialise(PiEngine::EmulationMode::T, PiGraphics::Orientation::T) (in MyGame) (GlfwGraphicsSystem.cpp:29)
5 MyGame 0x343f1f MacOSXEngine::Initialise() (in MyGame) (MacOSXEngine.cpp:581)
6 MyGame 0x342f8f main (in MyGame) (MacOSXEngine.cpp:304)
7 MyGame 0x3445 start (in MyGame) + 53
을
실행중인 모듈 내의 프레임에 대해서만 함수 + 파일 + 행 번호를 생성합니다. 코드는 OSX에서만 작동하지만 다른 플랫폼에서 작동하도록 조정할 수 있습니다. 커버되지 않은 코너 케이스가있을 것입니다,하지만 잘하면 이것은 좋은 출발점입니다. 코드는 다음과 같습니다
namespace ExceptionHandler
{
char m_ExeFilename[ PATH_MAX ];
// Execute cmd store stdout into buf (up to bufSize).
int Execute(const char * cmd, char * buf, size_t bufSize)
{
char filename[ 512 ];
sprintf(filename, "%d.tmp", rand());
if (FILE * file = fopen(filename, "w"))
{
if (FILE * ptr = popen(cmd, "r"))
{
while (fgets(buf, bufSize, ptr) != NULL)
{
fprintf(file, "%s", buf);
}
pclose(ptr);
}
fclose(file);
unlink(filename);
return 0;
}
return -1;
}
// Resolve symbol name and source location given the path to the executable and an address
int Addr2Line(char const * const program_name, void const * const addr, char * buff, size_t buffSize)
{
char addr2line_cmd[512] = {0};
sprintf(addr2line_cmd, "atos -d -o %.256s %p", program_name, addr);
return Execute(addr2line_cmd, buff, buffSize);
}
// Check if file exists.
bool FileExists(const char * filename)
{
if (FILE * fh = fopen(filename, "r"))
{
fclose(fh);
return true;
}
return false;
}
// Print stack trace.
void PrintStackTrace()
{
int trace_size = 0;
char ** messages = (char **)NULL;
static const size_t kMaxStackFrames = 64;
static void * stack_traces[ kMaxStackFrames ];
trace_size = backtrace(stack_traces, kMaxStackFrames);
messages = backtrace_symbols(stack_traces, trace_size);
for (int i = 0; i < trace_size; ++i)
{
int stackLevel;
char filename[ 512 ];
uintptr_t address;
char symbol[ 512 ];
uintptr_t symbolOffset;
uintptr_t functionOffset;
bool symbolOffsetValid = false;
bool somethingValid = true;
if (sscanf(messages[ i ], "%d%*[ \t]%s%*[ \t]%" SCNxPTR "%*[ \t]%" SCNxPTR "%*[ \t]+%*[ \t]%" SCNuPTR, &stackLevel, filename, &address, &symbolOffset, &functionOffset) == 5)
{
symbolOffsetValid = true;
}
else if (sscanf(messages[ i ], "%d%*[ \t]%s%*[ \t]%" SCNxPTR "%*[ \t]%s%*[ \t]+%*[ \t]%" SCNuPTR, &stackLevel, filename, &address, symbol, &functionOffset) == 5)
{
}
else
{
somethingValid = false;
}
const size_t BUFF_SIZE = 4096;
char buff[ BUFF_SIZE ] = { '\0' };
if (somethingValid)
{
if (symbolOffsetValid && symbolOffset == 0)
{
fprintf(stderr, "%3d %-32s %#16" PRIxPTR " %#" PRIxPTR " + %" PRIuPTR "\n", stackLevel, filename, address, symbolOffset, functionOffset);
}
else if (FileExists(m_ExeFilename) && Addr2Line(m_ExeFilename, stack_traces[ i ], buff, BUFF_SIZE) == 0)
{
fprintf(stderr, "%3d %-32s %#16" PRIxPTR " %s", stackLevel, filename, address, buff);
}
else
{
fprintf(stderr, "%3d %-32s %#16" PRIxPTR " %#" PRIxPTR " + %" PRIuPTR "\n", stackLevel, filename, address, symbolOffset, functionOffset);
}
}
else
{
fprintf(stderr, "%s\n", messages[ i ]);
}
}
if (messages)
{
free(messages);
}
}
void Handler(int sig, siginfo_t * siginfo, void * context)
{
switch(sig)
{
case SIGSEGV:
fputs("Caught SIGSEGV: Segmentation Fault\n", stderr);
break;
case SIGBUS:
fputs("Caught SIGBUG: Bus error (bad memory access)\n", stderr);
break;
case SIGINT:
fputs("Caught SIGINT: Interactive attention signal, (usually ctrl+c)\n", stderr);
break;
case SIGFPE:
switch(siginfo->si_code)
{
case FPE_INTDIV:
fputs("Caught SIGFPE: (integer divide by zero)\n", stderr);
break;
case FPE_INTOVF:
fputs("Caught SIGFPE: (integer overflow)\n", stderr);
break;
case FPE_FLTDIV:
fputs("Caught SIGFPE: (floating-point divide by zero)\n", stderr);
break;
case FPE_FLTOVF:
fputs("Caught SIGFPE: (floating-point overflow)\n", stderr);
break;
case FPE_FLTUND:
fputs("Caught SIGFPE: (floating-point underflow)\n", stderr);
break;
case FPE_FLTRES:
fputs("Caught SIGFPE: (floating-point inexact result)\n", stderr);
break;
case FPE_FLTINV:
fputs("Caught SIGFPE: (floating-point invalid operation)\n", stderr);
break;
case FPE_FLTSUB:
fputs("Caught SIGFPE: (subscript out of range)\n", stderr);
break;
default:
fputs("Caught SIGFPE: Arithmetic Exception\n", stderr);
break;
}
break;
case SIGILL:
switch(siginfo->si_code)
{
case ILL_ILLOPC:
fputs("Caught SIGILL: (illegal opcode)\n", stderr);
break;
case ILL_ILLOPN:
fputs("Caught SIGILL: (illegal operand)\n", stderr);
break;
case ILL_ILLADR:
fputs("Caught SIGILL: (illegal addressing mode)\n", stderr);
break;
case ILL_ILLTRP:
fputs("Caught SIGILL: (illegal trap)\n", stderr);
break;
case ILL_PRVOPC:
fputs("Caught SIGILL: (privileged opcode)\n", stderr);
break;
case ILL_PRVREG:
fputs("Caught SIGILL: (privileged register)\n", stderr);
break;
case ILL_COPROC:
fputs("Caught SIGILL: (coprocessor error)\n", stderr);
break;
case ILL_BADSTK:
fputs("Caught SIGILL: (internal stack error)\n", stderr);
break;
default:
fputs("Caught SIGILL: Illegal Instruction\n", stderr);
break;
}
break;
case SIGTERM:
fputs("Caught SIGTERM: a termination request was sent to the program\n", stderr);
break;
case SIGABRT:
fputs("Caught SIGABRT: usually caused by an abort() or assert()\n", stderr);
break;
default:
break;
}
PrintStackTrace();
fflush(stderr);
fflush(stdout);
_exit(1);
}
bool Initialise(const char * argv)
{
char path[ PATH_MAX ];
uint32_t size = sizeof(path);
if (_NSGetExecutablePath(path, &size) == 0)
{
if (! realpath(path, m_ExeFilename))
{
strcpy(m_ExeFilename, path);
}
}
else
{
strcpy(m_ExeFilename, argv ? argv : "");
}
struct sigaction sig_action = {};
sig_action.sa_sigaction = Handler;
sigemptyset(&sig_action.sa_mask);
sig_action.sa_flags = SA_SIGINFO;
int toCatch[ ] = {
SIGSEGV,
SIGBUS,
SIGFPE,
SIGINT,
SIGILL,
SIGTERM,
SIGABRT
};
bool okay = true;
for (size_t toCatchIx = 0; toCatchIx < PiArraySize(toCatch); ++toCatchIx)
{
okay &= sigaction(toCatch[ toCatchIx ], &sig_action, NULL) == 0;
}
return okay;
}
}
int main(int argc, char ** argv)
{
argc = argc;
argv = argv;
ExceptionHandler::Initialise(argc > 0 ? argv[ 0 ] : NULL);
// Do something
return 0;
}
내가 맥 OSX 10.7에서 GCC/LLVM-GCC를 사용, 감사합니다 :) –
귀하의'callstack' 변수가 그래서 이것은 64 비트 시스템에서 작동하지 않습니다 잘못된 유형입니다. 'int' 대신'void *'를 사용하십시오. – SoapBox
대단히 감사합니다 :) –