Portabilität: std::string::npos

Datumsansicht Baumansicht Betreffansicht Attachement-Sicht

Autor: Christian Weisgerber (naddy_at_mips.inka.de)
Datum: 14. Aug 2002


Ich stoße öfters auf Programmkonstrukte, die sich unbemerkt vom
Autors als unportabel erweisen. Besteht Interesse daran, dass ich
solche Probleme gelegentlich hier aufzeige, damit jemand daraus
lernen kann?

Mein heutiger Fall stammt aus GNUMP3d.

| class CTheme
| {
...
| std::string m_theme;
...
| }

| int CTheme::isValid()
| {
| std::string loc = m_themeDir + "/" + m_theme + "/";
|
| /*
| * Make sure there's no directory traversal in the theme name.
| */
| if ( m_theme.find( ".." ) != (unsigned int)-1 )
| {
| return 0;
| }
| if ( m_theme.find( "/" ) != (unsigned int)-1 )
| {
| return 0;
| }
...
| }

Das Erstaunliche ist, dass diese Funktion hier schon im ersten if
zurückkehrt, auch wenn der fragliche String nachweislich kein ".."
enthält.

Bleibt der Vergleich. Tatsächlich liefert std::string::find() bei
Nichtfinden die Konstante std::string::npos zurück. Nun, wird
mancher sagen, das ist doch als die größte vorzeichenlose Ganzzahl
festgelegt, was auf einer Zweierkomplementmaschine (also überall)
dasselbe wie -1 ist. Wo ist das Problem?

Die Länge eines std::string ist vom Typ size_type, was typischerweise
size_t ist. Und das ist auf einer 64-Bit-Maschine eben ein unsigned
long zu 64 Bit, während unsigned int ein 32-Bit-Wert ist. Letzterer
wird für den Vergleich *vorzeichenrichtig* auf 64 Bit erweitert.
Da er nach dem Cast unsigned ist, wird also mit 0x00000000FFFFFFFF
verglichen, während std::string::npos den Wert 0xFFFFFFFFFFFFFFFF
hat.

Auf einer 32-Bit-Maschine wird man den Unterschied nie merken, auf
einer 64-Bit-Maschine fliegt es einem um die Ohren.

Bei Verwendung von std::string::npos, wie in der API vorgesehen,
wäre das nicht passiert.

-- 
Christian "naddy" Weisgerber                          naddy_at_mips.inka.de

Datumsansicht Baumansicht Betreffansicht Attachement-Sicht

Dieses Archiv wurde generiert von hypermail 2.1.4 : 14. Aug 2002 CEST