【问题标题】:Get current execution path from within C library从 C 库中获取当前执行路径
【发布时间】:2014-01-30 06:18:42
【问题描述】:

我正在用 C 语言编写一个记录器库,目前正在尝试使用 addr2line 获得更好的回溯输出。为此,我需要能够获取当前可执行文件的路径。目前我只关心 linux,但也会为 Mac OS 支持而努力。

对于 linux 支持,我尝试使用 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,但之后的一切都是胡言乱语。

为什么我这样获取不到当前的执行路径?

【问题讨论】:

    标签: c linux backtrace addr2line


    【解决方案1】:
    char* exe_path          = (char*)malloc( 255 );
    // ...
    readlink( "/proc/self/exe", exe_path, sizeof( exe_path ) )
    

    exe_path 是一个指针,所以它的大小将等于 sizeof(char*)(4 或 8),而不是 255。

    exe_path 更改为char[255] 或将呼叫更改为sizeof

    顺便说一句,readlink 不会附加 NULL 字节,所以你应该这样做:

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

    【讨论】:

    • 谢谢!这正是问题所在!
    猜你喜欢
    • 1970-01-01
    • 2018-10-17
    • 2017-04-16
    • 2019-11-14
    • 2015-07-09
    • 2011-02-07
    相关资源
    最近更新 更多