2013-07-17 3 views
13

다음 코드는 초기화 할 수없는 변수가 있습니다. GCC는 초기화되지 않은 변수를보고하는 방법에gcc 초기화되지 않은 변수의 경고를하지 못함

$ cat a.c 
int foo(int b) { 
    int a; 
    if (b) 
    a = 1; 
    return a; 
} 

$ gcc-4.7 -c -Wall -Wmaybe-uninitialized -o a.o ./a.c 
$ gcc-4.7 -v 
Using built-in specs. 
COLLECT_GCC=gcc-4.7 
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.7/lto-wrapper 
Target: x86_64-linux-gnu 
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.7.3-2ubuntu1~12.04' --with-bugurl=file:///usr/share/doc/gcc-4.7/README.Bugs --enable-languages=c,c++,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.7 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.7 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --with-system-zlib --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu 
Thread model: posix 
gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-2ubuntu1~12.04) 

모든 단서 : GCC가 경고를 생성하는 것이 아니라해야한다는 것?

+0

컴파일러가 b가 항상 0이 아닌 값으로 설정되어 있는지 확인하는 데 충분한 기회가 있습니까? –

+0

@MichaelDorgan, OP의 예에는 * 다른 코드가 없습니다. –

+0

그걸 잡지 못했어요. 나는 "main"이 정의되지 않았으므로 다른 코드가 있어야한다고 생각했다 ... –

답변

10

당신이 볼 수없는 것처럼 보입니다 - this bug report을 참조하십시오. (그리고 this one은 그 것과 똑같은 테스트 케이스를 가지고 있습니다.) 근본 원인 버그가 거의 10 년이 된 것처럼 보이므로 해결하기가 쉽지 않은 것처럼 보입니다. 사실, 제가 링크 된 두 번째 버그는 "결코 고쳐지지 않을 것입니다."라는 문구가 있으므로, 잘 보이지 않습니다.

a.c:3:7: warning: variable 'a' is used uninitialized whenever 'if' condition is 
     false [-Wsometimes-uninitialized] 
    if (b) 
    ^
a.c:5:10: note: uninitialized use occurs here 
    return a; 
     ^
a.c:3:3: note: remove the 'if' if its condition is always true 
    if (b) 
    ^~~~~~ 
a.c:2:8: note: initialize the variable 'a' to silence this warning 
    int a; 
    ^
     = 0 
1 warning generated. 
+0

My clang (3.0 버전)은'-Wsometimes-initialize'도'-Wmaybe-uninitialized'도 인식하지 않습니다. 위에서 -Wconditional-uninitialized 또는 -Weverything을 사용하여 경고를 생성 할 수있었습니다. – clandau

+1

Clang 3.0은 꽤 오래되었습니다. –

4

문제는 GCC는 당신이 함수를 호출합니다 알 수 없다는 것입니다 :

당신에게 정말 중요한 경우

, clang 캐치 -Wall에 포함되어 -Wsometimes-uninitialized이 하나를 수행합니다 제로 인수. 이 경우 테스트 할 때가끔 그렇게하는 것이 좋겠지 만 일반적인 경우는 훨씬 어렵습니다. 고려 :

int foo(int b) { 
    int a; 
    switch(b) { 
    case 1: 
    a = 1; 
    break; 
    case 2: 
    a = 0; 
    break; 
    case 3: 
    a = 2; 
    break; 
    } 
    return a; 
} 

이 누구의 인터페이스 계약 감소함으로써 당신은 단지 1, 2, 3 그것을 전달하고 "초기화되지 않은"경고가이 경우에 가짜 것,하고 있다는 것입니다 완벽하게 합리적인 함수가 될 것이다 컴파일러의 경고 발생에 대한 신호 대 잡음 비율.

컴파일러가 이와 같은 상황에 대해 더 나은 진단을 제공하면 좋겠지 만 쉽지는 않지만 오류에 대한 경고는 항상 경고에 대한 해결 방법과 함께 코드를 어수선하게 만드는 것 사이에서 미묘한 균형을 유지합니다. 버그를 잡아라.

+0

위의 예는'-gun 매뉴얼 '(http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Warning-Options.html)에서'-Wuninitialized'에 대한 예제와 정확히 일치합니다. 그것이 말했듯이, 그 이유 때문에 "이 경고는 선택 사항"이됩니다. 명백하게, 그것은 틀렸고, 경고를 얻는 옵션이 없습니다. – clandau

+1

이러한 경우, 나는'-Wuninitialized' 또는'-Wall'을 명시 적으로 켰을 때 기꺼이 허위 사실, 일명 허위 경고를 받아 들일 것입니다. 현재 모든 위양성 (false negative)보다 훨씬 바람직합니다. 즉, 위양성이 있어야 할 때 경고가 없습니다. 컴파일러가 안정적으로 알아낼 수 없다면, 인간도 안정적으로 그렇게 할 수 없으므로, 가변 변수는 intialiser를 가져야한다. –

1

uninitializedTest.c :

여기
#include <stdio.h> 
#include <stdlib.h> 


int main(void) 
{ 
    int result; 
    if(rand()) 
     result = 1; 

    printf("%d\n", result); 

    return 0; 
} 

몇 가지 테스트가 실행 :

$ avr-gcc -Os -Wuninitialized -o uninitializedTest uninitializedTest.c 
$ gcc-4.2 -Os -Wuninitialized -o uninitializedTest uninitializedTest.c 
$ gcc-4.0 -Os -Wuninitialized -o uninitializedTest uninitializedTest.c 
uninitializedTest.c: In function ‘main’: 
uninitializedTest.c:32: warning: ‘result’ may be used uninitialized in this function 

$ gcc-4.2 -Os -Wmaybe-uninitialized -o uninitializedTest uninitializedTest.c 
cc1: error: unrecognized command line option "-Wmaybe-uninitialized" 
$ gcc-4.2 -Os -Wuninitialized -o uninitializedTest uninitializedTest.c 
$ gcc-mp-4.8 -Os -Wuninitialized -o uninitializedTest uninitializedTest.c 
$ gcc-mp-4.8 -Os -Wmaybe-uninitialized -o uninitializedTest uninitializedTest.c 

AVR-GCC 4.8 (또한 AVR-GCC-4.4.5으로 들키지)

gcc-4.0이 문제를 인식 할 수있는 것으로 보입니다.

$ gcc-4.0 -v 
Configured with: /var/tmp/gcc/gcc-5493~1/src/configure --disable-checking -enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.0/ --with-gxx-include-dir=/include/c++/4.0.0 --with-slibdir=/usr/lib --build=i686-apple-darwin9 --program-prefix= --host=powerpc-apple-darwin9 --target=powerpc-apple-darwin9 
Thread model: posix 
gcc version 4.0.1 (Apple Inc. build 5493) 

그래서 ... 라이센스가 부여 된 Apple 특정 제품 이었습니까? 아니면 애플이 오픈 소스에서 멀어지고있는 이유 일 수도 있습니다 ... 10 년된 버그를 고쳐서 gcc 커뮤니티가 그것을 받아들이지 않았습니까?

1

어떤 종류의 최적화를 활성화해야합니다. 예를 들어, -O2를 사용하여 예제를 다시 컴파일하면 경고가 나타납니다.

코드 경로를 분석해야하기 때문에 계산 비용이 많이 들기 때문에 GCC는 코드 최적화를 요구할 때만 사용할 수 있습니다.

+0

이것은 나를 위해 일했습니다. 불행히도 -O2 없이는이 동작을 얻을 수 없습니다. –