Обучающие курсы:

Обучение профессии "Разработчик C#" + стажировка в Mail.ru
Обучение профессии "Разработчик Python" + трудоустройство
Обучение профессии "Веб-разработчик" + стажировка в Mail.ru


Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей







1. Компилируйте без замечаний при максимальном уровне предупреждений

Резюме

Следует серьезно относиться к предупреждениям компилятора и использовать максимальный уровень вывода предупреждений вашим компилятором. Компиляция должна выполняться без каких-либо предупреждений. Вы должны понимать все выдаваемые предупреждения и устранять их путем изменения кода, а не снижения уровня вывода предупреждений.

Обсуждение

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

Успешная сборка программы должна происходить молча (без предупреждений). Если это не так, вы быстро приобретаете привычку не обращать внимания на вывод компилятора и можете пропустить серьезную проблему (см. рекомендацию 2).

Чтобы избежать предупреждений, надо понимать, что они означают, и перефразировать ваш код так, чтобы устранить предупреждения и сделать предназначение кода более понятным как для компилятора, так и для человека.

Делайте это всегда — даже если программа выглядит корректно работающей. Делайте это, даже если убедились в мягкости предупреждения. Даже легкие предупреждения могут скрывать последующие предупреждения, указывающие на реальную опасность.

Примеры

Пример 1. Заголовочный файл стороннего производителя. Библиотечный заголовочный файл, который вы не можете изменить, может содержать конструкцию, которая приводит к (вероятно, мелкому) предупреждению. В таком случае "заверните" этот файл в свой собственный, который будет включать исходный при помощи директивы #include и избирательно отключать для него конкретные предупреждения. В своем проекте вы будете использовать собственный заголовочный файл, а не исходный. Например (учтите — управление выводом предупреждений варьируется от компилятора к компилятору):

// Файл:   myproj/my_lambda.h -  "обертка" для  lambda.hpp из
// библиотеки  Boost.   Всегда включайте именно этот файл  и  не
// используйте lambda.hpp непосредственно.   Boost.Lambda
// приводит к выводу компилятором предупреждений,  о
// безвредности которых нам доподлинно известно,   когда
// разработчики сделают новую версию,   которая не будет
// вызывать  предупреждений,   мы удалим из  этого файла
// соответствующие директивы #pragma,   но сам заголовочный
// файл останется.
//
#pragma warning(push)  // Отключение  предупреждений только
                       // для данного заголовочного файла
#pragma warning(disable:4512)
#pragma warning(disable:4180)
#include  <boost/lambda/lambda.hpp>
#pragma warning(pop)    // восстанавливаем исходный уровень
                        // вывода предупреждений

Пример 2. "Неиспользуемый параметр функции". Убедитесь, что вы в самом деле сознательно не используете параметр функции (Например, это "заглушка" для будущего расширения или требуемая стандартом часть сигнатуры, которую ваш код не использует). Если этот параметр вам действительно не нужен, просто удалите его имя:

//  ...   внутри пользовательского распределителя  подсказка не
// используется   ...
// Предупреждение: "неиспользуемый параметр 'localityHint'"
pointer allocate( size_type numObjects,
                  const void * "localityHint = 0 ) {
    return static_cast<pointer>(
            mallocShared( numObjects * sizeof(T) ) );
}

// новая версия: предупреждение устранено
pointer allocate( size_type numObjects,
                  const void * /* localityHint */ = 0 ) {
    return static_cast<pointer>(
            mallocShared( numObjects * sizeof(T) ) );
}

Пример 3. "Переменная определена, но не используется". Убедитесь, что вы действительно не намерены обращаться к данной переменной (к таким предупреждениям часто приводят локальные объекты, следующие идиоме "выделение ресурса есть инициализация", см. рекомендацию 13). Если обращение к объекту действительно не требуется, часто можно заставить компилятор замолчать, включив "вычисление" самой переменной в качестве выражения (такое вычисление не влияет на скорость работы программы):

// Предупреждение: "переменная 'lock' определена, но не
// используется"
void Fun() {
    Lock lock;
    // ...
}

// новая версия: предупреждение не должно выводиться
void Fun() {
    Lock lock;
    lock;
    // ...
}

Пример 4. "Переменная может использоваться, не будучи инициализированной". Инициализируйте переменную (см. рекомендацию 19).

Пример 5. "Отсутствует return". Иногда компиляторы требуют наличия инструкции return несмотря на то, что поток управления не может достичь конца функции (например, при наличии бесконечного цикла, инструкции throw, других инструкций return). Такое предупреждение не стоит игнорировать, поскольку вы можете только думать, что управление не достигает конца функции. Например, конструкция switch, у которой нет выбора default, при внесении изменений в программу может привести к неприятностям, так что следует иметь выбор default, который просто выполняет assert(false) (см. также рекомендации 68 и 90):

// предупреждение: отсутствующий "return"
int Fun( Color с ) {
    switch( с ) {
        case Red: return 2;
        case Green: return 0;

Стр.18

        case Blue:
        case  Black:  return  1;
    }
}
// Новая версия: предупреждение устранено
int Fun( Color с ) {
    switch( с ) {
        case Red: return 2;
        case Green: return 0;
        case Blue:
        case Black: return 1;
        // Значение !"string" равно false:
        default:
            assert(!"should never get here!");
            return  -1;
    }
}

Пример 6. "Несоответствие signed/unsigned". Обычно не возникает необходимость сравнивать или присваивать числа с разным типом знаковости. Измените типы сравниваемых переменных так, чтобы они соответствовали друг другу. В крайнем случае, воспользуйтесь явным преобразованием типов. (Компилятор все равно вставляет в код преобразование типов и предупреждает именно об этом, так что лучше сделать то же самостоятельно.)

Исключения

Иногда компилятор может выдавать утомительные, а порой и просто ложные предупреждения, но у вас нет способа их устранения (или такой способ заключается в нереальной или непроизводительной переделке текста программы). В таких редких случаях по решению всей команды разработчиков можно пойти на отключение конкретных мелких предупреждений, которые на самом деле не несут никакой особой информации и являются не более, чем результатом чрезмерной осторожности компилятора. Такие предупреждения можно отключить, но только данные конкретные предупреждения, а не все, максимально локализовав при этом область отключения и сопроводив ее ясным и подробным комментарием, почему такой шаг необходим.



 
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru