Учитывая, что:
1) Стандарт С++ 03 не затрагивает существование потоков каким-либо образом.
2) Стандарт С++ 03 оставляет за собой возможность реализовать, чтобы std::string
использовать семантику Copy-on-Write в своем конструкторе-копире
3) Семантика Copy-on-Write часто приводит к непредсказуемому поведению в многопоточной программе
Я прихожу к следующему, казалось бы, спорный, вывод:
Вы просто не можете безопасно и портативно использовать std::string в многопоточной программе
Очевидно, что структура данных STL не является потокобезопасной. Но, по крайней мере, с помощью std::vector, например, вы можете просто использовать мьютексы для защиты доступа к вектору. При реализации std::string, использующей COW, вы не можете надежно сделать это без редактирования семантики подсчета ссылок в рамках реализации поставщика.
Пример реального мира:
В моей компании у нас есть многопоточное приложение, которое было тщательно протестировано и прошло через Valgrind бесчисленное количество раз. Приложение работало месяцами без каких-либо проблем. Однажды я перекомпиляю приложение на другую версию gcc, и внезапно я получаю случайные segfaults все время. Valgrind теперь сообщает о недопустимых доступах к памяти в пределах libstdС++ в конструкторе std::string.
Итак, каково решение? Ну, конечно, я мог бы typedef std::vector<char>
как строковый класс, но на самом деле это отстой. Я также могу дождаться С++ 0x, и я молюсь, чтобы разработчики отказались от COW. Или, (дрожь), я мог бы использовать собственный класс строк. Я лично всегда выступаю против разработчиков, которые реализуют свои собственные классы, когда существующая библиотека будет работать нормально, но, честно говоря, мне нужен класс строк, который, я уверен, не использует семантику COW; и std::string просто не гарантирует этого.
Я прав, что std::string
просто нельзя использовать надежно вообще в переносных многопоточных программах? И что хорошего обходного пути?