Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #103, ИЮЛЬ 2007 г.

Трюки от Крыса

Крис Касперски

Хакер, номер #103, стр. 103-120-3

А вот язык Си++, претендующий на обратную совместимость с Си, при работе с диграфами наталкивается на серьезные проблемы, приобретая неоднозначность интерпретации: одна и та же конструкция может быть прочитана двояко в зависимости от того, выполнять ли в ней подстановку диграфов или нет.

Рассмотрим ситуацию на следующем примере. Допустим, в глобальном пространстве имен (global namespace) мы имеем класс, именуемый (для определенности) X. Допустим также, что мы хотим передавать класс X какому-нибудь другому классу в качестве аргумента (например, классу std::vector), причем передавать не абы как, а непременно в виде шаблона (template), ведь шаблоны - это, во-первых, очень модно, а во-вторых, жутко (не)удобно! Но как бы там ни было (о вкусах не спорят), задача поставлена, и ее надо решать.

Очевидное решение — написать «std::vector<::X>», и на некоторых компиляторах это будет работать. Как ты уже, наверное, понял, этими компиляторами окажутся Microsoft Visual C++, Borland C++, ранние версии GCC, то есть все те, кто не поддерживает диграфов и потому трактует конструкцию «std::vector<::X>» однозначно.

Проблемы возникают при попытке скормить эту штуку свежим версиям GCC (или любому другому компилятору с поддержкой диграфов). Комбинация «<:» заменяется «[», в результате чего вся конструкция превращается в «std::vector[:X>», выдавая ошибку транслятора и вызывая естественное недоумение программиста: «Что здесь не так?! Ведь еще вчера компилировалось!»

Одно из возможных решений состоит в разделении «<» и «::X>» символом пробела. Конструкция принимает вид «std::vector< ::X>», и конфликтов с диграфами больше не возникает.

Анализ исходных текстов, выловленных на бескрайних просторах Сети, показывает, что очень многие программы Си++ страдают подобными конфликтами и отказываются компилироваться свежими версиями GCC. Забавно, но некоторые разработчики прямо указывают требуемую версию транслятора в FAQ, предостерегая от использования более новых («багистных») версий. В действительности это не баг. Это фича! И теперь ты знаешь, как с ней обращаться.

Назад на стр. 103-120-2  Содержание