Cライブラリ内から現在の実行パスを取得します
質問
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
ですが、その後すべてのものは純粋なギブリッシュです。
このように現在の実行パスを取得できないのはなぜですか?
解決
char* exe_path = (char*)malloc( 255 );
// ...
readlink( "/proc/self/exe", exe_path, sizeof( exe_path ) )
.
exe_pathはポインタであるため、サイズは255ではなく、サイズ(char *)(4または8)に等しくなります。
exe_path
をchar[255]
に変更するか、呼び出しをsizeof
BTW、ReadLinkはNULLバイトを追加しませんので、このようなことをする必要があります。
len = readlink( "/proc/self/exe", exe_path, sizeof( exe_path ) )
exe_path[len] = 0;
. 所属していません StackOverflow