is your code portable?

September 29, 2011

Когда я пытаюсь разобраться в новом коде - я беру свой любимый компилятор и пытаюсь пофиксить (или хотя-бы рассмотреть) большинство предупреждений, которые он выдает. Потом выворачиваю уровень выдачи предупреждений на максимум и всё начинаю сначала.

gcc -Wall -W -Wextra -Weff-c++
gcc --help=warnings # и еще штук 20 из этого списка :]

Сам я это делаю, чтобы смотреть в чужой код было веселее. Побочным эффектом получается более переносимый (а часто и более корректный) код.

Сегодня рассмотрим пару предупреждений, которые мне выкопал gcc на реальном коде, который у нас (пока) собирается только под винду. Для этого я собрал кросс-компилятор mingw32-gcc и попытался его заюзать.

Пример 1:

/*
 * warning: operation on 'block_size' may be undefined
 */
block_size = ((block_size << 1) < block_size) ? 0: (block_size <<= 1);
/*
 * В одном выражении переменнй 'block_size' присваивается 2 (одинаковых) значения:
 *     block_size = ... (block_size <<= 1);
 *
 * Кстати, с '(block_size << 1) < block_size' тоже надо быть осторожным:
 *     компилятор может счесть целочисленное переполнение неопределенным поведением
 *     (в gcc отключается через -fwrapv) и выполнять только false ветвь.
 */

Пример 2:

// warning: left-hand operand of comma expression has no effect
if (hRoot == 0 ||
    lpSubKey == NULL,
    lpValue == NULL)
{
    return FALSE;
}
/*
 * С виду всё хорошо, но ',' во второй строке делает выражение очень веселым :]
 * Предупреждение говорит, что всё, что до запятой не имеет никакой силы.
 */

Сами ошибки, конечно, не являются виндоспецифичными, но они зарыты посреди непортабельного кода. Его хотелось бы компилировать чем-то более параноидальным, чем MSVS. Как видим, у gcc неплохо получается.

Как бонус - реже коммитим код, который не компилируется только под виндой :]