Nie używaj unsigned jako indeksu string-a

Oto niewinnie wyglądający kawałek kodu:

string theString = ...;
unsigned theIndex = theString.find(...);
if(theIndex != string::npos)
{
   // Znaleziono, robimy coś z theString[theIndex]
}
else
{
   // Nie znaleziono
}

który pięknie i poprawnie działa na Windows czy Linuxie.

Próba przeniesienia na Digital Unix (czy inną platformę 64-bitową) powoduje, że powyższy program zrzuca core lub się zawiesza.

Cały problem wynika z użycia unsigned zamiast string::size_type jako typu wyniku theString.find(). Na Digital Unixe string::size_type jest "większe" niż unsigned, w szczególności gdy find zwraca string::npos, zostaje to obcięte i porównanie wyniku find z string::npos zwraca zawsze "różne". W związku z tym, gdy czegoś, czego szukamy nie ma:

  • dobierając się do s[otrzymany_index] robimy coredump
  • pętle typu while(theIndex != string::npos) nigdy się nie kończą

Poprawka jest trywialna: trzeba używać string::size_type a nie unsigned, int, long czy cokolwiek bądź innego. Czyli np. w powyższym przypadku musi być

string::size_type theIndex = ...
komentarze obsługiwane przez Disqus