2017-01-31 3 views
1

Ich verwende strerror_r in einer Protokollierungshelferfunktion. Wie die man-Seite beschreibt, gibt es zwei Versionen dieser Funktion. Die POSIX-Version gibt einen int zurück. Die GNU-Version gibt eine Zeichenfolge (char *) zurück.Strerror_r ist falsch auf Alpine Linux

Als solche, so dass mein C++ Code mehr tragbar ist, ich einen Code-Block ähnlich wie diese haben:

char buffer[1000]; 
    int size = 1000; 
    int result = 0; 
    char* msg = buffer; 
    buffer[0] = '\0'; 
#ifdef _GNU_SOURCE 
    msg = strerror_r(err, buffer, size); 
#else 
    result = strerror_r(err, buffer, size); 
    if (result != 0) 
    { 
     sprintf(buffer, "unknown error: %d", err); 
    } 
#endif 
    LogToFile(msg); 

In dem obigen Code-Block, wird es entweder verwenden Version von strerror_r auf Anwesenheit abhängig von _GNU_SOURCE, die IMMER von g ++ festgelegt wird, da libstdC++ es erfordert. Auf Mac und anderen Unix-Versionen wird die POSIX-Version verwendet.

Jetzt funktioniert dieser Code für eine lange Zeit bis heute gut. Ein Benutzer versucht, meinen Code auf Alpine Linux und berichtete diese Compiler-Fehler heute auf der Linie strerror_r

main.cpp:16:21 error: invalid conversion from 'int' to 'char*' [-fpermissive] 

Welche diese Linie bildet mit zu kompilieren:

#ifdef _GNU_SOURCE 
    msg = strerror_r(err, buffer, size); 

Einen Höhepunkt auf dieser Plattform an den /usr/include/string.h enthüllt die folgenden:

Welche scheint, dass egal, welche Compiler-Umgebung verwendet wird, die einzige deklarierte versio n von strerror_r ist die POSIX-Version, die einen int zurückgibt. Das erklärt, warum der Fehler aufgetreten ist.

Ohne Benutzern zu sagen, dass sie manuell #undef _GNU_SOURCE oder die Quelle ändern, wie kann ich arbeiten, um dieses, so dass der Code tragbar sein weiter? Globales undefiniertes _GNU_SOURCE ist wahrscheinlich ein Nicht-Starter, da dies C++ ist (und wie oben erwähnt, von libstdC++ benötigt). Ich versuche zu sehen, ob es eine andere Makro-Kombination geben würde, für die ich testen könnte, aber ich bin nicht in der Lage, etwas Offensichtliches zu finden.

+0

Die offizielle Makroprüfung (gemäß der Handbuch-Seite verlinkt auf) ist '(_POSIX_C_SOURCE> = 200112L || _XOPEN_SOURCE> = 600) &&! _GNU_SOURCE' ist wahr, wenn die POSIX-Version bereitgestellt wird, andernfalls wird die GNU-Version bereitgestellt. Das bedeutet, dass Ihre Überprüfung ausreichen sollte, um sicherzustellen, dass die GNU-Version bereitgestellt wird, und die C-Bibliothek in Alpine Linux scheint fehlerhaft oder veraltet zu sein. –

+0

Wickeln Sie es in Ihrer eigenen Funktion. Machen Sie es flexibel genug, um beide Varianten zu verwenden. –

+0

@ n.m. Kannst du es ausarbeiten? Es ist bereits in einer Funktion verpackt ... – selbie

Antwort

5

Sie Vorteil von C nehmen ++ Funktion Überlastung:

char* check_error(int result, char* buffer, int err) { 
    if(result) 
     sprintf(buffer, "unknown error: %d", err); 
    return buffer; 
} 

char* check_error(char* result, char*, int) { 
    return result; 
} 

Und und loszuwerden bedingter Kompilierung in der Nutzung:

char buffer[1000]; 
buffer[0] = '\0'; 
char* msg = check_error(strerror_r(err, buffer, sizeof buffer), buffer, err); 
LogToFile(msg); 
+0

Danke. Ich weiß nicht, warum ich selbst nicht daran gedacht habe. Scheint jetzt so offensichtlich. – selbie

Verwandte Themen