2010-03-09 13 views
10

A gibt es irgendwelche g ++ Optionen, die falsche Initialisierung von std :: string mit NULL const char * erkennen können?Fehlerhafte std :: string Initialisierung mit NULL const char * mit Hilfe von g ++

war ich in den Prozess der einige int Felder in std :: string diejenigen drehen, das heißt:

struct Foo 
{ 
    int id; 
    Foo() : id(0) {} 
}; 

... verwandelte sich in:

struct Foo 
{ 
    std::string id; 
    Foo() : id(0) {} //oooops! 
}; 

ich ganz schlecht 'id' übersehen Initialisierung mit 0 und g ++ gab mir überhaupt keine Warnungen. Dieser Fehler wurde in der Laufzeit entdeckt (std :: string Konstruktor hat eine Exception geworfen), aber ich würde gerne solche Sachen in der Kompilierzeit finden. Gibt es irgendeinen Weg?

+2

Leider ist 0 der einzige Wert, der bei einer ungültigen Konvertierung von int in pointer keinen Fehler auslöst. Natürlich ist 0 eine Null-Zeiger-Konstante und kann daher in jeden beliebigen Zeigertyp umgewandelt werden. Ich weiß nichts von dem, was Sie tun können, außer wie der Besucher sagt, schreiben Sie diesen Initialisierer überhaupt nicht. –

+0

Die richtige Lösung wäre gewesen, einen privaten Konstruktor 'std :: string :: string (int);' hinzuzufügen. Das wäre eine bessere Übereinstimmung und verursacht daher einen Kompilierungsfehler. – MSalters

+1

Nicht sicher, ob Sie es so gemeint haben, aber das könnte tatsächlich funktionieren, als ein einmaliger Test, um irgendwelche Fehler zu finden, die aus dieser Runde von Änderungen von "int" zu "string" resultieren. Ändern Sie 'std :: basic_string' in den Standard-Kopfzeilen von g ++, überprüfen Sie, dass der neue Code kompiliert wird, und ändern Sie ihn dann schnell zurück, bevor irgendjemand es bemerkt. –

Antwort

5

Ich denke, es ist eigentlich undefiniertes Verhalten und nicht vom Compiler überprüft. Sie haben Glück, dass diese Implementierung eine Ausnahme auslöst.

Sie können jedoch solche Probleme vermeiden, indem Sie angeben, dass Sie oder Null-Initialisierung in einer Art unabhängige Weise Standard wollen:

struct Foo 
{ 
    X id; 
    Foo() : id() {} //note empty parenthesis 
}; 
+0

Hm ... also Sie sagen Standardkonstruktor für Int-Typ weist 0 zu? – pachanga

+3

Diese Syntax bedeutet Zero-Initialisierung für integrierte Typen. – visitor

+0

Danke für die Info! – pachanga

2

Es ist Infrastruktur in GCC genau diese Art der Warnung zu erzeugen:

void foo(const char* cstr) __attribute__((nonnull (1))); 

void bar() { 
    foo(0); 
} 

wenn sie mit -Wnonnull zusammengestellt (die durch -Wall impliziert ist) erzeugt:

warning: null argument where non-null required (argument 1) 

Also im Prinzip sollten Sie in der Lage sein, die entsprechenden System-Header zu ändern (oder besser für das Experimentieren, ändern Sie Ihre eigenen $ HOME/bits/basic_string.h kopieren und dann das System ein mit -isystem $HOME außer Kraft setzen) ähnlich:

basic_string(const _CharT* __s, const _Alloc& __a = _Alloc()) 
    __attribute__((nonnull (1))); 

Allerdings hilft das nicht, weil (zumindest in 4.0.1) -Wnonnull in C++ nicht unterstützt wird und das Attribut anscheinend ignoriert wird. Es ist nicht offensichtlich, warum das so ist; vielleicht hatte es den Eindruck, dass es schlecht mit Überlastung oder so etwas interagierte.

+1

Tatsächlich überprüft Ihr 'basic_string' ctor' __attribute __ ((nonnull (1))) 'oben, dass der' this' Zeiger nicht 'NULL' ist; ändern Sie einfach zu '__attribut __ ((nonnull (2)))', um zu überprüfen, dass '__s' nicht-null ist; siehe http://gcc.gnu.org/ml/gcc/2006-04/msg00549.html – vladr

7

Ich kann nicht einen Weg finden diese zur Compile-Zeit zu erfassen, so schrieb ich einen String-Builder-Funktion, die richtig behandelt Null-Zeiger: Diese

// FUNCTION :  safe_string(char const* pszS) 
// PARAMATERS : pszS  source string to build a string from (may be NULL or 0-length) 
// DESCRIPTION : Safely builds a string object from a char*, even a NULL pointer 
// RETURNS :  string 

template<class C> 
inline basic_string<C> safe_string(const C* input) 
{ 
    if(!input) 
     return basic_string<C>(); 
    return basic_string<C>(input); 
} 

ich verwenden, wenn ich eine Zeichenfolge erstellen und Es besteht die Möglichkeit, dass die Eingabe NULL ist.