20 октября 2008 г.

GCC и precision loss

В процессе портирования нашего линуксового проекта на Windows обнаружилась интересная вещь: наш компилятор GCC не умеет распознавать ситуации с присвоением из long в short и им подобные. То есть, распознавать, скорее всего, умеет, а вот сообщать о них — нет.

Вот простой пример:

int main (int argc, char **argv)
{
  unsigned long a = 0xFFFFFFFE;
  unsigned char b = a + 1;
  return 0;
}

Я, честно говоря, был немало удивлен. Специально этим вопросом не занимался, но был уверен, что такие ситуации GCC отслеживать умеет. Ан нет... Что самое интересное, большинство моих знакомых гуру тоже были в этом уверены. В нашем проекте, как и во многих других, известных мне проектах, используется GCC 4.1.2, некоторые используют 4.2. Вроде бы есть опция -Wconversion, но работает она только для fixed и floating point. В общем, подстава.

Думаю, что о важности такого предупреждения говорить не нужно. В MSVC++ эта ситуация легко отслеживается включением третьего уровня предупреждений — /W3. После портирования нашего проекта на MSVC++, мы смогли легко локализовать и исправить несколько ошибок, связанных как раз с некорректным преобразованием типов.

Но самое интересное не в этом. После длительного изучения документации по GCC, все-таки нашел :)

Итак, не прошло и 25 лет, как разработчики GCC все таки прониклись пользой отслеживания размерности типов. Начиная с версии 4.3 (первый релиз вышел в марте 2008 года, то есть, всего полгода назад) GCC умеет распознавать и сообщать о ситуациях с присваиманием из long в char и им подобных.

Опция -Wconversion, которая работала только для fixed и floating point теперь разделена на две опции -Wtraditional-conversion и -Wconversion. Подробности можно почитать здесь http://gcc.gnu.org/wiki/NewWconversion

Я проверил — на приведенный пример ругается "warning: conversion to ‘short unsigned int’ from ‘long unsigned int’ may alter its value". Аллелуйа!

Ура, товарищи! Даешь новые версии! Даешь новые баги! :)

1 комментарий:

  1. Удивляться этому - значит не до конца понять "философию" Си. А эта особенность лежит именно в языке, а не компиляторе, который просто правильно его реализует. Даже включать по умолчанию подобные предупреждения разработчики компилятора не станут, потому что тогда могут вызвать шквал критики со стороны профессионалов, таких как Линус Торвальдс. После очередного обновления gcc, он заявил, что компилятор стал выдавать слишком много предупреждений и если бы он хотел использовать язык, который заставляет писать правильно - взял бы Паскаль, а так - он специалист и лучше знает.

    ОтветитьУдалить