2014-01-11 17 views
0

저는 C 로거 라이브러리를 작성 중이며 addr2line을 사용하여 더 나은 백 트레이스 출력을 얻으려고하고 있습니다. 이렇게하려면 현재 실행 파일의 경로를 가져올 수 있어야합니다. 지금은 리눅스에 관심이 있지만 Mac OS 지원을 위해 촬영 될 것입니다. 리눅스 지원에 대한C 라이브러리 내에서 현재 실행 경로 가져 오기

나는 현재 실행 파일의 경로를 해결하기 위해 readlink()/proc/self/exe를 사용하려고 해요 :

static char** getPrettyBacktrace(void* addresses[], int array_size) { 
    // Used to return the strings generated from the addresses 
    char** backtrace_strings = (char**)malloc(sizeof(char) * array_size); 
    for(int i = 0; i < array_size; i ++) { 
     backtrace_strings[i] = (char*)malloc(sizeof(char) * 255); 
    } 

    // Will hold the command to be used 
    char* command_string = (char*)malloc(255); 
    char* exe_path   = (char*)malloc(255); 

    // Used to check if an error occured while setting up command 
    bool error = false; 

    // Check if we are running on Mac OS or not, and select appropriate command 
    char* command; 
    #ifdef __APPLE__ 
     // Check if 'gaddr2line' function is available, if not exit 
     if(!system("which gaddr2line > /dev/null 2>&1")) { 
      command = "gaddr2line -Cfspe"; 
      // TODO: get path for mac with 'proc_pidpath' 
     } else { 
      writeLog(SIMPLOG_LOGGER, "Function 'gaddr2line' unavailable. Defaulting to standard backtrace. Please install package 'binutils' for better stacktrace output."); 
      error = true; 
     } 
    #else 
     // Check if 'addr2line' function is available, if not exit 
     if(!system("which addr2line > /dev/null 2>&1")) { 
      command = "addr2line -Cfspe"; 
      if(readlink("/proc/self/exe", exe_path, sizeof(exe_path)) < 0) { 
       writeLog(SIMPLOG_LOGGER, "Unable to get execution path. Defaulting to standard backtrace."); 
       error = true; 
      } 
     } else { 
      writeLog(SIMPLOG_LOGGER, "Function 'addr2line' unavailable. Defaulting to standard backtrace. Please install package 'binutils' for better stacktrace output."); 
      error = true; 
     } 
    #endif 

    // If an error occured, exit now 
    if(error) { 
     free(backtrace_strings); 
     free(command_string); 
     free(exe_path); 
     return NULL; 
    } 

    for(int i = 0; i < array_size; i++) { 
     // Compose the complete command to execute 
     sprintf(command_string, "%s %s %X", command, exe_path, addresses[i]); 

     // Execute the command 
     FILE* line = popen(command_string, "r"); 

     // Get the size of the command output 
     int line_size = fseek(line, 0, SEEK_END); 

     // Read the output into the return string 
     fgets(backtrace_strings[i] , line_size, line); 

     // Close the command pipe 
     pclose(line); 
    } 

    return backtrace_strings; 
} 

readlink()에 의해 반환되는 경로는 다음과 같습니다 /home/nax��?. 첫번째 부분은 정확합니다 : /home/na, 그 이후의 모든 것은 순수한 횡설수설입니다.

이 방법으로 현재 실행 경로를 가져올 수없는 이유는 무엇입니까?

답변

2
char* exe_path   = (char*)malloc(255); 
// ... 
readlink("/proc/self/exe", exe_path, sizeof(exe_path)) 

exe_path 포인터이므로 크기가 char[255]로 (숯 *) (4, 8)이 아닌 255

변화 exe_path를를 sizeof 또는 sizeof

로 호출을 변경 동일 윌

btw, readlink는 NULL 바이트를 추가하지 않으므로 다음과 같이해야합니다.

len = readlink("/proc/self/exe", exe_path, sizeof(exe_path)) 
exe_path[len] = 0; 
+0

감사합니다! 그게 정확히 문제 였어! – PseudoPsyche