Frage

Ich schreibe eine Logger-Bibliothek in C und versuche derzeit, mithilfe von eine bessere Backtrace-Ausgabe zu erhalten addr2line.Dazu muss ich den Pfad der aktuellen ausführbaren Datei ermitteln können.Im Moment mache ich mir nur Sorgen um Linux, werde aber auch die Unterstützung von Mac OS in Betracht ziehen.

Für Linux-Unterstützung versuche ich zu verwenden readlink() Und /proc/self/exe So lösen Sie den Pfad der aktuellen ausführbaren Datei auf:

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;
}

Der Pfad, der zurückgegeben wird readlink() Ist: /home/nax��?.Der erste Teil ist richtig: /home/na, aber alles danach ist reines Kauderwelsch.

Warum kann ich auf diese Weise den aktuellen Ausführungspfad nicht abrufen?

War es hilfreich?

Lösung

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

exe_path ist ein Zeiger, daher entspricht seine Größe sizeof(char*) (4 oder 8), nicht 255.

ändern exe_path Zu char[255] oder ändern Sie den Anruf auf sizeof

Übrigens hängt readlink das NULL-Byte nicht an, also sollten Sie so etwas tun:

len = readlink( "/proc/self/exe", exe_path, sizeof( exe_path ) )
exe_path[len] = 0;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top