C 및 C ++ 프로그램을 컴파일 할 때 "항상 컴파일러 경고를 활성화해야"한다는 말을 자주 듣습니다. 왜 이것이 필요한가요? 어떻게합니까?
때때로 나는 또한 "경고를 오류로 취급해야한다"고 들었습니다. 내가해야합니까? 어떻게합니까?
C 및 C ++ 프로그램을 컴파일 할 때 "항상 컴파일러 경고를 활성화해야"한다는 말을 자주 듣습니다. 왜 이것이 필요한가요? 어떻게합니까?
때때로 나는 또한 "경고를 오류로 취급해야한다"고 들었습니다. 내가해야합니까? 어떻게합니까?
답변:
C 및 C ++ 컴파일러는 기본적 으로 다음과 같은 일반적인 프로그래머 실수를보고하는 데 악명이 높습니다 .
return
함수에서 값을 잊어 버리다printf
과 scanf
일치하지 않는 인수 및 패밀리이들은 일반적으로 기본적으로가 아니라 감지 및보고 될 수 있습니다. 이 기능은 컴파일러 옵션을 통해 명시 적으로 요청해야합니다.
이것은 컴파일러에 따라 다릅니다.
마이크로 소프트 C 및 C ++ 컴파일러는 스위치처럼 이해 /W1
, /W2
, /W3
, /W4
와 /Wall
. 적어도 사용하십시오 /W3
. /W4
및 /Wall
시스템 헤더 파일에 대한 가짜 경고를 방출하지만 프로젝트가 이러한 옵션 중 하나를 깨끗하게 컴파일하면, 그것은 갈 수 있습니다. 이 옵션은 상호 배타적입니다.
대부분의 다른 컴파일러와 같은 옵션을 이해 -Wall
, -Wpedantic
하고 -Wextra
. -Wall
필수적이며 나머지는 모두 권장됩니다 (이름에도 불구하고 모든-Wall
경고가 아닌 가장 중요한 경고 만 활성화 함 ). 이러한 옵션은 개별적으로 또는 모두 함께 사용할 수 있습니다.
IDE에는 사용자 인터페이스에서이를 활성화하는 방법이있을 수 있습니다.
컴파일러 경고는 코드에서 잠재적으로 심각한 문제를 나타냅니다. 위에 나열된 문제는 거의 항상 치명적입니다. 다른 사람이있을 수도 있고 아닐 수도 있지만 , 잘못된 경보로 판명 되더라도 컴파일이 실패하기를 원합니다 . 각 경고를 조사하고 근본 원인을 찾아서 수정하십시오. 잘못된 경보의 경우 경보를 해결하십시오. 즉, 다른 언어 기능을 사용하거나 경고가 더 이상 트리거되지 않도록 구성하십시오. 이것이 매우 어려운 것으로 판명되면 사례별로 특정 경고를 비활성화하십시오.
모든 경고가 잘못된 경고 인 경우에도 경고를 경고로 남기고 싶지는 않습니다. 방출되는 총 경고 수가 7 개 미만인 매우 작은 프로젝트의 경우 문제가되지 않을 수 있습니다. 더 오래되고 친숙한 오래된 홍수에서 새 경고가 사라지기 쉽습니다. 허용하지 마십시오. 모든 프로젝트를 깔끔하게 컴파일하십시오.
이것은 프로그램 개발에 적용됩니다. 소스 형식으로 프로젝트를 전세계에 배포하는 경우 릴리스 된 빌드 스크립트 -Werror
에서 제공 하거나 이에 상응 하지 않는 것이 좋습니다 . 사람들은 다른 버전의 컴파일러 또는 다른 컴파일러를 사용하여 프로젝트를 빌드하려고 할 수 있습니다. 다른 컴파일러는 다른 경고 세트를 사용할 수 있습니다. 그들의 빌드가 성공하기를 원할 것입니다. 경고 메시지를 보는 사람들이 사용자에게 버그 보고서 나 패치를 보낼 수 있도록 경고를 계속 사용하는 것이 좋습니다.
이것은 컴파일러 스위치로 다시 수행됩니다. /WX
Microsoft를위한 것이며 대부분의 사람들은을 사용 -Werror
합니다. 두 경우 모두 경고가 생성되면 컴파일이 실패합니다.
C는 HLL과 마찬가지로 다소 낮은 수준의 언어입니다. C ++은 C보다 상당히 고급 언어 인 것처럼 보이지만 여전히 많은 특성을 공유합니다. 이러한 특성 중 하나는 프로그래머, 특히 자신이하는 일을 아는 프로그래머를 위해 언어가 프로그래머에 의해 설계되었다는 것입니다.
[이 답변의 나머지 부분에서는 C에 중점을 둘 것입니다. 제가 말할 내용의 대부분은 C ++에도 적용됩니다. Bjarne Stroustrup이 유명하게 말했듯이, "C는 발로 쉽게 쏠 수있게 해주 며 C ++는 그것을 어렵게하지만, 그렇게하면 다리 전체를 날려 버립니다." ]
당신이하고있는 일을 알고 있다면, 정말로 하고있는 것을 알고 있다면 때때로 "규칙을 어겨 야"할 수도 있습니다. 그러나 대부분의 경우, 대부분의 사람들은 선의의 규칙으로 인해 우리 모두가 어려움을 겪지 않으며 항상 규칙을 위반하는 것이 좋지 않다는 데 동의합니다.
그러나 C 및 C ++에는 "나쁜 아이디어"이지만 공식적으로 "규칙에 대해"하지 않는 놀라운 일이 많이 있습니다. 때때로 그들은 때때로 나쁜 생각입니다 (그러나 다른 때는 방어 할 수 있습니다). 때때로 그들은 거의 항상 나쁜 생각입니다. 그러나 전통은 항상 이런 것들에 대해 경고 하지 않았습니다 . 다시 말하지만, 프로그래머는 자신이하는 일을 알고 있고, 정당한 이유 없이이 일을하지 않을 것이고, 무리에 의해 짜증날 것이라고 가정합니다 불필요한 경고.
물론 모든 프로그래머가 자신이하는 일을 실제로 아는 것은 아닙니다 . 특히, 모든 C 프로그래머는 (어떻게 경험이 있든) 시작 C 프로그래머가되는 단계를 거칩니다. 심지어 숙련 된 C 프로그래머조차도 부주의하게 실수를 할 수 있습니다.
마지막으로 경험에 따르면 프로그래머는 실수를 저지를뿐 아니라 이러한 실수가 실제로 심각한 결과를 초래할 수 있습니다. 실수를 저지르고 컴파일러가 경고하지 않고 프로그램이 즉시 충돌하거나 그로 인해 명백히 잘못된 것을하지 않으면 실수가 발생할 때까지 실수로 숨어있을 수 있습니다. 정말 큰 문제.
따라서 대부분 경고는 좋은 생각입니다. 심지어 숙련 된 프로그래머 (실제로, 그것은 "입니다 배운 특히 균형, 경고는 해를보다 더 잘하는 경향이, 숙련 된 프로그래머 배운")이 있습니다. 고의로 잘못한 일을하고 경고가 귀찮은 일이있을 때마다, 실수로 실수를 한 일이 적어도 10 회 정도 일어 났을 때 경고로 인해 더 이상 문제를 피할 수있었습니다. 그리고 대부분 "경고 한"일을하고 싶을 때 대부분의 경고를 비활성화하거나 해결할 수 있습니다.
(예 : "실수"의 전형적인 예는 테스트입니다 if(a = b)
당신이 경우 어떤 경우에도 기본적으로하지만 -. 대부분의 시간이 실수 요즘 그것에 대해 경고 그래서 대부분의 컴파일러입니다. 정말 모두 할당에 원 b
을 a
테스트 결과적으로을 입력하여 경고를 비활성화 할 수 있습니다 if((a = b))
.)
두 번째 질문은 왜 경고를 오류로 취급하도록 컴파일러에 요청 하시겠습니까? 나는 그것이 인간의 본성, 특히, "아, 그것은 단지 경고 일 뿐이다. 그렇게 중요하지 않다. 나중에 정리할 것이다"라고 말하는 너무 쉬운 반응 때문이라고 말하고 싶다. 그러나 당신이 미루는 사람이라면 (그리고 나는 당신에 대해 모르지만, 나는 끔찍한 미루는 사람입니다) 기본적으로 항상 정리를 끝내는 것이 쉽습니다-그리고 경고를 무시하는 습관에 빠지면, 그것은 무시하고있는 모든 메시지 가운데 눈에 띄지 않고 중요한 경고 메시지 를 놓치기가 쉬워졌습니다 .
따라서 컴파일러에게 경고를 오류로 처리하도록 요청하는 것은이 인간의 우월을 극복하기 위해 스스로 할 수있는 약간의 비법입니다.
개인적으로, 나는 경고를 오류로 취급하는 것에 대해 단호하지 않습니다. (실제로 솔직히 말하면 "개인"프로그래밍에서 해당 옵션을 실제로 활성화하지 않는다고 말할 수 있습니다.) 그러나 스타일 가이드 (나의 가이드)가있는 직장에서 해당 옵션을 활성화했는지 확인할 수 있습니다. ))의 사용을 의무화합니다. 그리고 나는 대부분의 전문 프로그래머가 말할 것이라고 생각합니다 .C의 오류로 경고를 처리하지 않는 상점은 무책임하게 행동하고 있지만 일반적으로 받아 들여지는 업계 모범 사례를 따르지 않습니다.
if(a = b)
수 없으므로 경고 할 필요가 없습니다." (그런 다음 누군가는이 특정 오류로 인해 10 개의 출시 된 제품에서 10 개의 중요 버그 목록을 생성합니다.) "알겠습니다. 숙련 된 C 프로그래머는 절대로 그것을 쓰지 않을 것입니다 ..."
if (returnCodeFromFoo = foo(bar))
한곳에서 코드를 캡처하고 테스트하기 위해 작성 하고 의미 할 수 있습니다 ( 유일한 목적은 foo
부작용이 있다고 가정하십시오 !) 실제로 경험 이 풍부한 프로그래머가 이것이 아는 것은 아니라는 사실 좋은 코딩 스타일은 지점 옆)
if (returnCodeFromFoo = foo(bar))
주석을 달고 경고를 끄십시오 (따라서 유지 관리 프로그래머가 4 년 후에 그것을 보았을 때 코드가 의도적이라는 것을 알게 될 것입니다. (Microsoft C ++에서) 누군가와 경고를 오류로 취급하는 것은 / Wall을 결합하는 것이 좋은 방법이라고 주장했습니다. (많은 억제 의견을
경고는 가장 숙련 된 일부 C ++ 개발자가 응용 프로그램을 만들 수있는 최선의 조언으로 구성됩니다. 그들은 가치가 있습니다.
Turing 완전한 언어 인 C ++에는 컴파일러가 사용자가하는 일을 알고 있다고 단순히 신뢰해야하는 경우가 많습니다. 그러나 컴파일러가 사용자가 작성한 내용을 쓰지 않았다는 것을 인식 할 수있는 경우가 많습니다. 전형적인 예는 printf와에 전달되는 인수, 또는 표준 : : 문자열과 일치하지 않는의 printf () 코드 (즉하지 않는 것이 지금까지 나에게 일이!). 이 경우 작성한 코드는 오류가 아닙니다. 컴파일러가 작동 할 수있는 유효한 해석이있는 유효한 C ++ 표현식입니다. 그러나 컴파일러에는 현대식 컴파일러가 쉽게 감지 할 수있는 것을 간과 한 강력한 직감이 있습니다. 이것들은 경고입니다. 그것들은 무시할 수있는 모든 엄격한 C ++ 규칙을 사용하여 컴파일러에게 명백한 것입니다.
경고를 끄거나 무시하는 것은 자신보다 숙련 된 사람들의 무료 조언을 무시하는 것과 같습니다. 허비에 대한 교훈은 태양에 너무 가까이 날아가서 날개가 녹거나 메모리 손상 오류가 발생하면 끝납니다. 둘 사이에서 나는 하늘에서 언제든 떨어지게 될 것이다!
"오류로 취급 경고"는이 철학의 극단적 인 버전입니다. 여기서 아이디어 는 컴파일러가 제공하는 모든 경고 를 해결 하는 것입니다. 모든 무료 조언을 듣고 그에 따라 행동하십시오. 이것이 개발에 적합한 모델인지 여부는 팀과 작업중인 제품 종류에 따라 다릅니다. 승려가 가질 수있는 금욕적인 접근법입니다. 일부에게는 훌륭하게 작동합니다. 다른 사람들에게는 그렇지 않습니다.
많은 응용 프로그램에서 경고를 오류로 취급하지 않습니다. 이러한 특정 응용 프로그램은 다양한 연령대의 여러 컴파일러가있는 여러 플랫폼에서 컴파일해야하기 때문에이 작업을 수행합니다. 때로는 다른 플랫폼에서 경고로 바뀌지 않고 한쪽에서 경고를 수정하는 것이 실제로 불가능하다는 것을 알 수 있습니다. 그래서 우리는 단지 조심합니다. 우리는 경고를 존중하지만 경고를 거꾸로 구부리지 않습니다.
equals
/ 작성을 막을 수는 없습니다 hashCode
).
다른 답변은 훌륭하며 나는 그들이 말한 것을 반복하고 싶지 않습니다.
제대로 다루지 않은 "경고 활성화"의 또 다른 측면은 코드 유지 관리에 큰 도움이된다는 것입니다. 크기가 큰 프로그램을 작성할 때는 모든 것을 한 번에 머리에 두는 것이 불가능 해집니다. 일반적으로 적극적으로 작성하고 생각하는 기능 또는 세 가지 기능과 참조 할 수있는 파일 또는 화면에 하나 또는 세 개의 파일이 있지만 대부분의 프로그램은 백그라운드에 존재하며이를 신뢰해야합니다. 계속 작동합니다.
경고를하고 가능한 한 활기차고 얼굴을 가꾸는 것은 변화하는 것이 보이지 않는 것에 문제가있을 경우 경고하는 데 도움이됩니다.
예를 들어, clang warning을 보자 -Wswitch-enum
. 열거 형에서 스위치를 사용하고 가능한 열거 형 값 중 하나를 누락하면 경고가 트리거됩니다. 아마도 당신이 생각하기 어려운 실수라고 생각할 수도 있습니다. 적어도 switch 문을 작성할 때 열거 형 값 목록을 보았을 것입니다. 사용자를위한 스위치 옵션을 생성하는 IDE가있을 수 있으며 사람의 실수에 대한 여지가 없습니다.
이 경고는 6 개월 후 열거 형에 다른 가능한 항목을 추가 할 때 실제로 발생합니다. 다시 말하지만, 문제의 코드에 대해 생각하고 있다면 아마 괜찮을 것입니다. 그러나이 열거 형이 여러 가지 다른 목적으로 사용되고 추가 옵션이 필요한 경우 중 하나 인 경우 6 개월 동안 만지지 않은 파일의 스위치를 업데이트하는 것을 잊어 버릴 수 있습니다.
자동화 된 테스트 사례를 생각할 때와 같은 방식으로 경고를 생각할 수 있습니다. 코드를 적절하게 작성하고 처음 작성할 때 필요한 작업을 수행하는 데 도움이되지만 더 확실하게 확인하는 데 도움이됩니다. 당신이 그것을 생산하는 동안 필요한 것을 계속하고 있습니다. 차이점은 테스트 케이스는 코드 요구 사항에 따라 매우 좁게 작동하며이를 작성해야하며 경고는 거의 모든 코드에 대한 합리적인 표준에 따라 광범위하게 작동하며 컴파일러를 만드는 관리자가 제공하는 관대함입니다.
예를 들어, 분할 오류를 디버깅하려면 프로그래머가 오류의 근본 원인 (원인)을 추적해야합니다.이 오류는 일반적으로 결국 오류의 원인이 된 행보다 코드의 이전 위치에 있습니다.
원인은 컴파일러가 무시한 경고를 발행 한 라인이고, 세그먼테이션 결함을 일으킨 라인이 결국 오류를 발생시킨 라인 인 것이 매우 일반적입니다.
경고를 수정하면 문제가 해결됩니다. 클래식!
위의 데모. 다음 코드를 고려하십시오.
#include <stdio.h>
int main(void) {
char* str = "Hello world!";
int idx;
// Colossal amount of code here, irrelevant to 'idx'
printf("%c\n", str[idx]);
return 0;
}
"Wextra"플래그로 컴파일 할 때 GCC에 전달되면 다음을 제공합니다.
main.c: In function 'main':
main.c:9:21: warning: 'idx' is used uninitialized in this function [-Wuninitialized]
9 | printf("%c\n", str[idx]);
| ^
이는 내가 할 수 무시하고 코드를 실행 .. 그리고 내 IP 에피쿠로스 교수 말을 사용 그때는 "그랜드"세그먼트 오류를 목격 할 것입니다 :
세그멘테이션 오류
실제 시나리오에서이를 디버깅하기 위해서는 세그먼테이션 오류를 일으키는 라인에서 시작하여 원인의 근본 원인을 추적하려고 시도합니다. 그들은 그 엄청난 양의 내부 i
및 str
내부에서 발생한 것을 검색해야합니다. 저기 코드 ...
언젠가 idx
는 초기화되지 않은 상태로 사용 되는 것을 발견 한 상황에서 자신을 발견 하기 때문에 가비지 값을 가지므로 문자열 범위를 벗어나 색인을 생성하여 세그먼트 화 오류가 발생합니다.
경고를 무시하지 않았다면 즉시 버그를 발견했을 것입니다!
str[idx]
" 아니다 "좋아, 어디에 str
및 idx
정의`?
idx
테스트에서 예상 한 값 (예상 값이 0 인 경우는 아님)이 될 수 있으며 실제로는 배포 할 때 인쇄해서는 안되는 민감한 데이터를 가리킬 수 있습니다.
경고를 오류로 취급하는 것은 자기 훈련의 수단 일뿐입니다. 반짝이는 새 기능을 테스트하기 위해 프로그램을 컴파일하고 있었지만 거친 부분을 고칠 때까지는 할 수 없었습니다 . 추가 정보는 없으며 Werror
우선 순위를 매우 명확하게 설정합니다.
기존 코드의 문제를 해결할 때까지 새 코드를 추가하지 마십시오
도구가 아닌 중요한 사고 방식입니다. 컴파일러 진단 출력은 도구입니다. MISRA (내장 C 용)는 또 다른 도구입니다. 어떤 것을 사용하든 중요하지는 않지만 컴파일러 경고는 가장 쉽게 얻을 수있는 도구 (설정할 플래그는 하나임)이며 신호 대 잡음비는 매우 높습니다. 따라서 사용 하지 않을 이유가 없습니다 .
완벽한 도구는 없습니다. 을 쓰면 const float pi = 3.14;
대부분의 도구는 정밀도가 나쁜 π를 정의했다는 것을 알려주지 않습니다. if(tmp < 42)
큰 프로젝트에서 변수에 무의미한 이름을 부여하고 마법의 숫자를 사용하는 것이 재앙이되는 방법으로 알려져 있지만 대부분의 도구는 눈썹을 높이 지 않습니다 . 작성 하는 "빠른 테스트"코드는 단지 테스트라는 것을 이해해야합니다. 테스트는 다른 작업으로 넘어 가기 직전에 코드를 가져와야하지만 여전히 단점이 있습니다. 해당 코드를 그대로두면 새 기능을 추가하는 데 2 개월을 소비 한 경우 디버깅이 훨씬 어려워집니다.
올바른 사고 방식에 도달하면을 사용할 필요가 없습니다 Werror
. 경고를 경고로 사용하면 시작하려는 디버그 세션을 실행하는 것이 적절한 지 또는 먼저 중단하고 경고를 수정해야하는지에 대한 정보를 바탕으로 결정을 내릴 수 있습니다.
레거시 임베디드 C 코드로 작업하는 사람으로서 컴파일러 경고를 활성화하면 수정 제안시 많은 약점과 영역을 조사 할 수있었습니다. gcc에서 활용 -Wall
하고 -Wextra
심지어 -Wshadow
중요해졌습니다. 모든 위험을 감수하지는 않겠지 만 코드 문제를 보여주는 데 도움이되는 몇 가지 항목을 나열하겠습니다.
이것은 완성되지 않은 작업과 문제가 될 수있는 모든 전달 된 변수를 사용하지 않는 영역을 쉽게 가리킬 수 있습니다. 이를 트리거 할 수있는 간단한 함수를 살펴 보겠습니다.
int foo(int a, int b)
{
int c = 0;
if (a > 0)
{
return a;
}
return 0;
}
-Wall 또는 -Wextra없이 이것을 컴파일하면 아무런 문제가 없습니다. - c
사용되지는 않지만 벽에 알려줍니다 .
foo.c : 함수 'foo'에서 :
foo.c : 9 : 20 : 경고 : 사용하지 않는 변수 'c'[-Wunused-variable]
-Wextra는 또한 매개 변수 b가 아무것도하지 않는다고 알려줍니다.
foo.c : 함수 'foo'에서 :
foo.c : 9 : 20 : 경고 : 사용하지 않는 변수 'c'[-Wunused-variable]
foo.c : 7 : 20 : 경고 : 사용하지 않는 매개 변수 'b'[-Wunused-parameter] int foo (int a, int b)
이것은 조금 어려워서 -Wshadow
사용될 때까지 나타나지 않았습니다 . 위의 예제를 추가하여 추가하면되지만 둘 다 사용하려고 할 때 많은 혼란을 유발하는 로컬과 이름이 같은 전역이 발생합니다.
int c = 7;
int foo(int a, int b)
{
int c = a + b;
return c;
}
-Wshadow를 켜면이 문제를 쉽게 발견 할 수 있습니다.
foo.c : 11 : 9 : 경고 : 'c'선언은 전역 선언을 가리 킵니다. [-Wshadow]
foo.c : 1 : 5 : 참고 : 그림자 선언은 여기에 있습니다
이것은 gcc에서 추가 플래그를 필요로하지 않지만 여전히 과거의 문제의 원인이었습니다. 데이터를 인쇄하려고 시도하지만 형식 오류가있는 간단한 함수는 다음과 같습니다.
void foo(const char * str)
{
printf("str = %d\n", str);
}
서식 플래그가 잘못되어 문자열이 인쇄되지 않으며 gcc는 이것이 원하는 것이 아니라고 알려줍니다.
foo.c : 함수 'foo'에서 :
foo.c : 10 : 12 : 경고 : 형식 '% d'은 (는) 'int'형식의 인수를 예상하지만 인수 2에는 'const char *'형식이 있습니다. [-Wformat =]
이것들은 컴파일러가 당신을 다시 확인할 수있는 많은 것들 중 세 가지입니다. 다른 사람들이 지적한 초기화되지 않은 변수를 사용하는 것과 같은 많은 것들이 있습니다.
possible loss of precision
"및 " comparison between signed and unsigned
"경고입니다. 나는 그것이 어렵다 "프로그래머는"이 무시 얼마나 많은 파악을 찾아 (사실, 내가 아니에요 정말 있는지 왜 오류 없음)
sizeof
가 부호가 없지만 기본 정수 유형이 부호 있기 때문이라고 생각합니다 . sizeof
결과 형은 size_t
일반적으로 정수가 "로서 사용되도록 의도되어 있지만, 전형적으로 예를 들어, 배향 또는 어레이 / 컨테이너 요소 수 등 활자 크기에 관련된 것도, 사용되는 int
그렇지 않으면 요구". 따라서 int
컨테이너를 반복하는 데 사용 하는 사람들의 수를 고려하면 (와 비교 int
하여 size_t
), 오류가 발생하면 거의 모든 것이 깨질 수 있습니다. ; P
이것은 C에 대한 구체적인 대답이며, 왜 이것이 다른 것보다 C에 더 중요한가.
#include <stdio.h>
int main()
{
FILE *fp = "some string";
}
이 코드는 경고 와 함께 컴파일됩니다 . 지구상의 다른 모든 언어 (조립 언어를 사용하지 않음) 에서 발생하는 오류는 C의 경고 입니다. C의 경고는 거의 항상 변장 오류입니다. 억제하지 말고 경고를 수정해야합니다.
함께 gcc
, 우리는 다음과 같이이 작업을 수행 gcc -Wall -Werror
.
이것은 또한 일부 MS 비보안 API 경고에 대한 보안 성이 높은 이유이기도합니다. C를 프로그래밍하는 대부분의 사람들은 경고를 오류로 취급하는 어려운 방법을 배웠으며,이 내용은 같은 종류의 것이 아니고 이식 불가능한 수정을 원했던 것으로 나타났습니다.
컴파일러 경고는 친구입니다 (소리를 내지 말고 강조하기 위해 대문자).
레거시 Fortran-77 시스템에서 작업합니다. 컴파일러는 귀중한 것들을 알려줍니다 : 사용하지 않는 변수 또는 서브 루틴 인수가있는 경우 값이 변수에 설정되기 전에 로컬 변수를 사용하여 서브 루틴 호출에서 인수 데이터 유형이 일치하지 않습니다. 이들은 거의 항상 오류입니다.
긴 게시물 피하기 : 내 코드가 깨끗하게 컴파일되면 97 %가 작동합니다. 내가 작업하는 다른 사람은 모든 경고를 끄고 컴파일하고 디버거에서 몇 시간 또는 며칠을 보낸 다음 나에게 도움을 요청합니다. 경고가 표시된 코드를 컴파일하고 수정해야 할 사항을 알려줍니다.
C ++의 컴파일러 경고는 몇 가지 이유로 매우 유용합니다.
1-작업의 최종 결과에 영향을 줄 수있는 실수를 한 부분을 보여줍니다. 예를 들어 변수를 초기화하지 않았거나 "=="대신 "="를 입력 한 경우 (예제 만 있음)
2-코드가 c ++ 표준을 준수하지 않는 위치를 보여줄 수도 있습니다. 코드가 실제 표준을 준수하면 코드를 다른 판형으로 쉽게 옮길 수 있기 때문에 유용합니다.
일반적으로, 경고는 사용자가 프로그램을 사용할 때 알고리즘 결과에 영향을 미치거나 일부 오류를 방지 할 수있는 코드의 실수가있는 위치를 나타내는 데 매우 유용합니다.
한때 전자 테스트 장비를 제조 한 대기업 (Fortune 50)에서 근무했습니다.
우리 그룹의 핵심 제품은 수백 년 동안 문자 그대로 수백 개의 경고를 생성하는 MFC 프로그램이었습니다. 거의 모든 경우에 무시되었습니다.
버그가 발생하면 끔찍한 악몽입니다.
그 직책 이후, 나는 새로운 스타트 업의 첫 개발자로 고용 될만큼 운이 좋았습니다.
컴파일러 경고 수준이 매우 시끄럽게 설정되어 모든 빌드에 대해 '경고 없음'정책을 권장했습니다.
우리는 연습을 위해 #pragma warning-push / disable / pop을 사용하여 개발자가 정말로 괜찮은 코드를 디버그 수준의 로그 문과 함께 사용하는 것이 좋습니다.
이 연습은 우리에게 잘 작동했습니다.
#pragma warning
경고를 억제하는 것이 아니라 의도적이며 우발적이지 않다는 것을 다른 프로그래머에게 신속하게 전달하는 이중 목적을 제공하며, 문제가 발생했을 때 잠재적으로 문제가있는 영역을 빠르게 찾을 수 있지만 오류 / 경고를 수정하지 않는 검색 태그 역할을합니다. 고치세요.
단지 거기에 하나의 경고를 오류로 치료와 문제 : 당신은 다른 소스에서 나오는 코드를 사용하는 경우 (예를 들어, 마이크로 $ ** t 라이브러리, 오픈 소스 프로젝트), 그들은 자신의 일 오른쪽을, 그들의 코드를 컴파일하면 발생하지 않았다 톤 경고.
나는 항상 이 경고 나 오류가 발생하지 않도록 내 코드를 작성하고 불필요한 잡음을 생성하지 않고 컴파일 할 때까지 그것을 청소. 내가 작업 해야하는 쓰레기가 나를 놀라게하고, 큰 프로젝트를 작성하고 컴파일이 처리 된 파일을 발표 해야하는 경고 스트림을보아야 할 때 놀랍습니다.
소프트웨어의 실제 평생 비용은 처음에는 소프트웨어를 작성하는 것이 아니라 유지 관리에서 비롯된다는 것을 알고 있기 때문에 코드를 문서화하지만 다른 이야기입니다 ...
-Wall
하고 사용 -Wall -Wextra
합니다.
일부 경고는 코드의 의미 상 오류 또는 UB 가능성을 의미 할 수 있습니다. 예 ;
를 들어 if()
, 미사용 변수, 로컬로 마스크 된 전역 변수 또는 부호있는 것과 부호없는 것의 비교. 많은 경고는 컴파일러의 정적 코드 분석기 또는 컴파일시 감지 가능한 ISO 표준 위반 ( "진단 필요")과 관련이 있습니다. 이러한 경우는 합법적 인 경우이지만 대부분 디자인 문제의 결과 일 수 있습니다.
gcc와 같은 일부 컴파일러에는 "오류로 경고"모드를 활성화하는 명령 줄 옵션이 있습니다. 잔인한 경우 초보자 코더를 교육하는 데 유용합니다.
C ++ 컴파일러 가 전혀 정의되지 않은 동작 을 초래하는 컴파일 코드를 받아 들인다는 사실은 컴파일러 의 주요 결함입니다. 그들이 이것을 고치지 않는 이유는 그렇게하면 쓸만한 빌드를 깨뜨릴 수 있기 때문입니다.
대부분의 경고는 빌드가 완료되지 못하게하는 치명적인 오류 여야합니다. 오류를 표시하고 어쨌든 빌드를 수행하는 기본값은 잘못되었으며 경고를 오류로 취급하고 경고를 남기기 위해 오류를 무시하지 않으면 프로그램이 중단되고 임의의 일이 발생할 수 있습니다.
int i; if (fun1()) i=2; if (fun2()) i=3; char s="abcde"[i];
경우에만 둘 경우이 코드 전시 정의되지 않은 동작을 fun1()
하고 fun2()
반환 할 수 있습니다 false
동일한 기능 실행에. 어느 것이 사실 일 수도 있고 아닐 수도 있지만, 컴파일러는 어떻게 말합니까?
편하게하세요 : 꼭 그럴 필요는 없습니다. -Wall 및 -Werror는 코드 리팩터링 미치광이에 의해 설계되었습니다. 컴파일러 개발자는 사용자 측에서 컴파일러 업데이트 후 기존 빌드를 중단하지 않기 위해 발명했습니다 . 이 기능은 아무것도 아니지만 빌드를 중단하거나 중단하기로 한 결정에 관한 것입니다.
사용 여부는 전적으로 귀하의 기호에 달려 있습니다. 실수를 해결하는 데 도움이되기 때문에 항상 사용합니다.
-Wall and -Werror was designed by code-refactoring maniacs for themselves.
[인용 필요]
-Wall
-Werror