Я пройшов і знайшов мінімальний набір включень, який повинен отримати максимальний рівень попередження. Потім я вилучив із цього списку набір попереджень, які, на мою думку, насправді не вказують на те, що відбувається щось погане, або в іншому випадку є занадто багато помилкових позитивних даних, щоб їх можна було використовувати в реальній збірці. Я коментував, чому кожен із тих, кого я виключав, був виключений. Це мій останній набір запропонованих попереджень:
Я включаю, -Wno-unused
тому що у мене часто є змінні, які я знаю, що буду використовувати пізніше, але ще не мають функціоналу, написаного для. Видалення попереджень про це дозволяє мені писати в моєму бажаному стилі, інколи відкладаючи реалізацію речей. Корисно вимикати це раз у раз, щоб переконатися, що нічого не прослизнуло через щілини.
-Wdisabled-optimization
здається, сильне налаштування параметрів користувача. Я щойно додав цей модуль до моєї збірки (лише для оптимізованих збірок з очевидних причин), і він нічого не повернувся, тому, здається, це не особливо балакане попередження, принаймні для способу кодування. Я включаю його (навіть незважаючи на те, що код, який викликає це попередження, не обов'язково є помилковим), оскільки я вірю в роботу зі своїми інструментами, а не проти них. Якщо gcc каже мені, що він не може оптимізувати код для того, як я його написав, то я повинен переглянути його перезапис. Я підозрюю, що код, який викликає це попередження, може отримати вигоду від того, що він буде більш модульним, незважаючи на те, що, хоча код технічно не є помилковим (можливо), стилістично він є.
-Wfloat-equal
попереджає про безпечне порівняння рівності (зокрема, порівняння з не обчисленим значенням -1). Прикладом мого коду, де я це використовую, є те, що у мене є вектор float. Я переглядаю цей вектор, і є деякі елементи, які я ще не можу оцінити, якими вони повинні бути, тому я встановив їх до -1,0f (оскільки моя проблема використовує лише додатні числа, -1 - поза домену). Пізніше я проходжу і оновлюю -1,0f значення. Це не просто піддається іншому методу роботи. Я підозрюю, що у більшості людей немає цієї проблеми, і порівняння точної кількості у плаваючій точці - це, мабуть, помилка, тому я включаю її до списку за замовчуванням.
-Wold-style-cast
в коді бібліотеки є багато хибних позитивних результатів. Зокрема, сімейство функцій htonl, які використовуються в мережах, а також реалізація шифрування Rijndael (AES), яку я використовую, має касти старого стилю, про які вона попереджає мене. Я маю намір замінити обидва ці, але я не впевнений, чи є в моєму коді щось інше, на що він скаржиться. Більшість користувачів, мабуть, повинні мати це за замовчуванням.
-Wsign-conversion
був жорстким (і майже не склав список). Увімкнувши його в моєму коді, генерується величезна кількість попереджень (100+). Майже всі вони були невинні. Однак я обережно використовував підписані цілі числа там, де я не був впевнений, хоча для моєї конкретної проблемної області я зазвичай отримував невелике підвищення ефективності, використовуючи непідписані значення через велику кількість цілого поділу, яке я роблю. Я пожертвував цією ефективністю, тому що мене хвилювало випадкове просування підписаного цілого числа до непідписаного, а потім ділення (що не є безпечним, на відміну від додавання, віднімання та множення). Увімкнення цього попередження дозволило мені безпечно змінити більшість моїх змінних на неподписані типи та додати кілька записів у деяких інших місцях. Наразі це трохи важко у використанні, оскільки попередження не таке розумно. Наприклад, якщо це зробитиunsigned short + (integral
constant expression)
, цей результат неявно передається до int. Потім він попереджає про потенційну проблему знаків, якщо ви призначите це значення
unsigned
або unsigned short
, навіть якщо це безпечно. Це, безумовно, найбільш необов’язкове попередження майже для всіх користувачів.
-Wsign-promo
: див -Wsign-conversion
.
-Wswitch-default
здається безглуздим (ви не завжди бажаєте випадку за замовчуванням, якщо ви чітко перерахували всі можливості). Однак увімкнення цього попередження може нав'язати щось, що, мабуть, є хорошою ідеєю. У випадках, коли ви явно хочете ігнорувати все, крім перерахованих можливостей (але можливі інші номери), тоді введітьdefault: break;
зробити це явним. Якщо ви чітко перераховуєте всі можливості, то ввімкнення цього попередження допоможе переконатися, що ви поставили щось на кшталт assert (false), щоб переконатися, що ви реально покрили всі можливі варіанти. Це дозволяє вам бути ясним у тому, що стосується вашої проблеми, і програмно виконує це. Однак вам доведеться бути обережними, просто скрізь дотримуючись твердження (помилкового). Це краще, ніж робити нічого у випадку за замовчуванням, але, як зазвичай, у арсеналі, він не буде працювати у версії версій. Іншими словами, ви не можете розраховувати на те, щоб перевірити номери, які ви отримаєте, скажімо, від мережевого з'єднання або бази даних, над якими не маєте абсолютного контролю. Винятки або повернення рано - найкращий спосіб вирішити це (але все-таки вимагати, щоб у вас був випадок за замовчуванням!).
-Werror
є для мене важливим. Складаючи велику кількість коду в багатопотоковій збірці з кількома цілями, попередження легко пропустити. Перетворення попереджень у помилки гарантує, що я їх помічаю.
Тоді є набір попереджень, які не включені до переліченого списку, тому що я не вважаю їх корисними. Це застереження та мої коментарі, чому я не включаю їх до списку за замовчуванням:
-Wabi
не потрібен, оскільки я не поєдную бінарні файли від різних компіляторів. Я намагався компілювати його все одно, і це не спрацьовує, тому це не здається багатослівним.
-Waggregate-return
я не вважаю помилкою. Наприклад, він спрацьовує при використанні циклу на основі діапазону на векторі класів. Оптимізація зворотної вартості повинна враховувати будь-які негативні наслідки цього.
-Wconversion
запускає цей код: short n = 0; n += 2;
Неявна конверсія в int викликає попередження, коли потім перетворюється назад у цільовий тип.
-Weffc++
включає попередження, якщо всі учасники даних не ініціалізовані у списку ініціалізатора. Я навмисно цього не роблю у багатьох випадках, тому набір попереджень занадто захаращений, щоб бути корисним. Корисно вмикати кожен раз і перевіряти інші попередження (наприклад, невіртуальні деструктори базових класів). Це було б корисніше як збірка попереджень (наприклад -Wall
), а не окреме попередження самостійно.
-Winline
відсутня, оскільки я не використовую вбудоване ключове слово для оптимізації, просто для визначення функцій, вбудованих у заголовки. Мені байдуже, чи оптимізатор насправді накреслює це. Це попередження також скаржиться, якщо воно не може вбудувати функцію, оголошену в тілі класу (наприклад, порожній віртуальний деструктор).
-Winvalid-pch
відсутня, оскільки я не використовую попередньо складені заголовки.
-Wmissing-format-attribute
не використовується, тому що я не використовую розширення gnu. Те саме -Wsuggest-attribute
і для кількох інших
Потенційно помітна його відсутність - це те -Wno-long-long
, чого я не потребую. Я компілюю з -std=c++0x
( -std=c++11
у GCC 4.7), що включає long long
цілі типи. Ті, хто затримався на C ++ 98 / C ++ 03, можуть подумати, що це виключення зі списку попереджень.
-Wnormalized=nfc
вже є типовим варіантом, і виглядає найкращим.
-Wpadded
увімкнено періодично, щоб оптимізувати компонування класів, але це не залишається увімкненим, оскільки не у всіх класах є достатньо елементів для видалення прокладки в кінці. Теоретично я міг отримати кілька додаткових змінних для "free", але не варто витрачати додаткових зусиль на підтримку цього (якщо розмір мого класу зміниться, видалити ці раніше вільні змінні непросто).
-Wstack-protector
не використовується, тому що я не використовую -fstack-protector
-Wstrict-aliasing=3
увімкнено -Wall
і є найбільш точним, але схоже, що рівень 1 і 2 дають більше попереджень. Теоретично нижчий рівень є "сильнішим" попередженням, але це ціною більше помилкових позитивних результатів. Мій власний тестовий код складено чисто під усі 3 рівні.
-Wswitch-enum
не поведінка, яку я хочу. Я не хочу чітко обробляти кожну операцію перемикання. Було б корисно, якби в мові був якийсь механізм активувати це у визначених операторах переключення (щоб гарантувати, що майбутні зміни до перерахунку обробляються скрізь, де вони повинні бути), але це буде надмірним для налаштування "все-чи-нічого".
-Wunsafe-loop-optimizations
викликає занадто багато помилкових попереджень. Може бути корисним застосовувати це періодично і вручну перевіряти результати. Як приклад, він створив це попередження у своєму коді, коли я перекинув усі елементи у векторі, щоб застосувати до них набір функцій (використовуючи діапазон для циклу). Це також попереджає для конструктора масиву const const std :: string (де це не цикл у коді користувача).
-Wzero-as-null-pointer-constant
і -Wuseless-cast
є попередженнями лише для GCC-4.7, які я додам під час переходу до GCC 4.7.
Я подав кілька звітів про помилки / запити на покращення в gcc в результаті деяких досліджень, тому, сподіваюся, я зможу врешті додати більше попереджень із списку "не включати" до списку "включити" . Цей список включає всі попередження, згадані в цій темі (плюс, я думаю, кілька додаткових). Багато попереджень, про які явно не згадується у цій публікації, включені як частина іншого попередження, яке я згадую. Якщо хтось помітить будь-які попередження, які повністю виключені з цієї публікації, дайте мені знати.
-Wall
) є-Wbloody_everything
прапор :-)