Ostrożnie z konstruktorem std::string
Niesłychanie użyteczna klasa std::string zawiera pułapkę. Wystarczy wykonać jakiś wariant polecenia
string s = (char *) 0;
a wiele implementacji standardowej biblioteki C++ spróbuje zaglądać do komórki pamięci o adresie 0.
Dwa-trzy lata temu gwałt pamięci następował w niemal wszystkich znanych mi implementacjach, ostatnio sytuacja się poprawia ale problem ciągle jest spotykany.
Problem jest poważniejszy niż się na pierwszy rzut oka wydaje: kodu takiego, jak powyższy raczej nikt nie napisze ale fragment taki jak poniżej:
string s = some_fun();
jest często spotykany a łatwo też pomylić kolejność parametrów czy zapomnieć o ciapkach i uzyskać coś w stylu
void some_fun(const string& a, const string& b, int c); ... some_fun("Mam", 0, 7);
Drugi z powyższych przypadków wyjdzie na jaw szybko. Ale w pierwszym, wystarczy, by some_fun() (będące np. funkcją z jakiejś zewnętrznej biblioteki) zwracało char * lub const char * i w niesłychanie rzadkich okolicznościach zdarzało się jej zwrócić zero jako sygnał błędu i nieszczęście gotowe.
Kilka lat temu straciłem sporo czasu poszukując przyczyny tajemniczych awarii od dawna wdrożonej i działającej bez problemów aplikacji. Jak się w końcu okazało, administratorzy zainstalowali jakiegoś patcha, w efekcie pojawiły się problemy bodajże z DNS a te zaburzyły działanie funkcji należącej do pewnej zewnętrznej biblioteki (zresztą wołanej tylko dla celów diagnostycznych) - która zdecydowała się zwracać 0...
Zabezpieczenie jest stosunkowo proste - trzeba napisać metodę
inline string cstr2string(const char *c) { return c ? c : ""; }
i pisać zawsze
string s = cstr2string(some_fun());
- «Strumienie w GCC nie lubią setw dla obiektów string
- Mądre przerzucanie wyjątków»
- ↑C++ - sztuczki i niebezpieczeństwa