2016-03-20 2 views
2

ich eine Warnung in meinem Code haben, der mich treibt verrückt:"Format-String ist kein Stringliteral" Korrektur der Warnung

int vasprintf_wrapper(char** bufptr, const char* fmt, va_list ap) 
{ 
    // Do stuff... 
    // ... 
    return vasprintf(bufptr, fmt, ap); 
} 

Clang (3.6.0), beschwert mit „Format-String ist kein String Literal ", bezogen auf das Argument fmt, das weitergeleitet wird.

Naiv, habe ich versucht zu:

return vasprintf(bufptr, reinterpret_cast<const char[]>(fmt), ap); 

Was natürlich nicht kompilieren.

Was mache ich? Das Deaktivieren der Warnung ist keine Option. Ich möchte die Warnung haben. Aber in diesem Fall möchte ich dem Compiler mitteilen, dass ich weiß, was ich mache ("berühmte letzte Worte" scherzt beiseite ...)

+0

Möglicherweise, und ich bin nicht 100% sicher, aber ich sehe nicht, wie dies eine gültige Konstante sein kann, wie Sie eine Variable übergeben (so kann es keine cosnant Zuweisung sein). Hast du versucht, diesen Teil zu entfernen? –

+0

@DavyC Du meinst die Besetzung? Ja, das gleiche Ergebnis mit oder ohne 'const'. –

Antwort

4

Sie können Clang sagen dass Ihr Parameter ein Printf-Format ist, das das Attribut Flag verwendet. Siehe the documentation

In Ihrem Fall, so etwas wie das funktionieren soll:

__attribute__((__format__ (__printf__, 2, 0))) 
int vasprintf_wrapper(char** bufptr, const char* fmt, va_list ap) 
{ 
... 
} 

Edit: Changed die letzten Parameter auf 0 gemäß Cornstalks' Vorschlag (schaltet sie aus Kontrolle für va_list Parameter).

+0

Ich denke, es sollte "__attribut __ ((__ format__ (__printf__, 2, 0)))" sein. Die [GCC-Dokumentation] (https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes) sagt: "* Für Funktionen, bei denen die Argumente nicht verfügbar sind, um überprüft zu werden (Wie vprintf), geben Sie den dritten Parameter als Null an. * "Aber ich mag Ihren Ansatz besser als meinen, weil er die Warnungen bei der Verwendung von' vasprintf_wrapper' beibehält, also +1 von mir. – Cornstalks

+0

Danke! Ich erinnere mich nicht an das Attribut "__format__", das überhaupt existiert. Der Vorschlag von Cornstalks (der letzte Parameter ist 0) funktioniert. Mit 3 kompiliert es nicht. –

4

Das Warnflag, das diese Art von Warnung aktiviert, ist -Wformat-nonliteral. Da Sie wollen nicht vollständig diese Warnung auszuschalten, können Sie lokal diese Warnung deaktivieren Sie den folgenden Code:

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Wformat-nonliteral" 

... 

#pragma clang diagnostic pop 

So Ihre Funktion würde wie folgt aussehen:

int vasprintf_wrapper(char** bufptr, const char* fmt, va_list ap) 
{ 
    // Do stuff... 
    // ... 

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Wformat-nonliteral" 
    return vasprintf(bufptr, fmt, ap); 
#pragma clang diagnostic pop 
} 
+0

Danke. Für den Datensatz funktioniert das ganz gut, aber es stellt sich heraus, dass das Attribut "__format__", wie in der anderen Antwort erwähnt, die Kompilierzeitprüfung tatsächlich auf den Aufrufer überträgt, was bedeutet, dass die Warnung nur ausgegeben wird, wenn die Funktion aufgerufen wird mit einem nicht-wörtlichen, anstatt bedingungslos ausgegeben werden. Also funktionieren beide Antworten, das Attribut ist sicherer, also habe ich das ausgewählt :-) –

+0

@NikosC. Gut, du solltest die andere Antwort wählen :) Es ist besser als meins. Ich werde meine hier lassen, nur für den Fall, dass jemand es nützlich findet. – Cornstalks