gcc 진단 메시지의 폐해

GunSmoke의 이미지

1원짜리 팁 정도 되나요?

정보문화사에서 나온 '쉽게 배우는 C 프로그래밍 테크닉'이라는 책을 보고 있습니다. 36페이지에 보면 단지 교육적인 목적만을 위해 제작된 전혀 실용적이지 않은 예제가 하나 나옵니다.

001          #include <stdlib.h>
002          int main()
003          {
004               init();
005               exit(0);
006          }
007
008          void init()
009          {}

예제의 컴파일 결과도 책에 제시되어 있습니다.

% gcc dummy.c -o dummy -warn -Wall
dummy.c: In function 'main' :
dummy.c:4: warning: implicit declaration of function 'init'
dummy.c: At top level:
dummy.c:9: warning: type mismatch with previous implicit declaration
dummy.c:4: warning: previous implicit declaration of 'init'
dummy.c:8: warning: 'init' was previously implicitly declared to return 'init'

보시는 바와 같이 implicit declaration을 설명하기 위한 예제입니다. 책에서 설명은 인자와 반환 형식을 알 수 없는 함수가 암시적 선언으로 'int init()'로 정의되어 있다고 가정하고 컴파일되어 8행 실제 정의의 반환 형식과 충돌된다고 얘기하고 있습니다.

그러나 이러한 gcc의 진단 메시지는 오해의 소지가 있습니다. 실재 암시적 선언이 발생하는 때는 init()를 호출하는 순간이고 암시적 선언이 사라지는 순간은 함수 본체를 구성하는 블럭이 끝나는 곳, 즉 6행이라는 것입니다. 따라서 8행에서 실재 init의 함수 정의가 나타나더라도 이미 암시적 선언이 통용범위에서 사라진 이후이므로 구현체는 init()의 함수 호출이 실제 정의된 함수의 데이터형과 호환되지 않는다는 사실을 알지 못하고 잘못된 프로그램을 성공적으로 컴파일할 수 있다는 것입니다.

그러나 예제의 진단메시지는 9행에서 type mismatch가 발생하고 있으므로 암시적 선언이 프로그램의 끝, 즉 파일 통용범위 끝에서 발생할 수 있다고 오해할 수 있습니다. gcc가 너무 똑똑하다보니 이런 문제가 생기는 것이구요.

ps1. c99에서는 과감하게 implicit declaration이 허락되지 않고 있습니다. 선언하지 않는 대상체는 아예 사용하지도 말라는 거죠 뭐.

Forums: 
나는오리의 이미지

플밍 책 보면
'암시적으로', '묵시적으로'라는 글들을 가끔 접합니다.
저 이런거 엄청 싫어합니다. ㅠ.ㅠ
컴파일러는 사람이 시키는데로만 하면되는데 왜 지가 알아서 버그를 수정하냐는거죠 ㅠ.ㅠ

main() {} 이것이 void main() {} 이렇게 되는것처럼...
(C99에서는 void main() {} 를 권장하는거 맞죠?)
앗싸리 main()앞에 반환형식이 선언되어있지 않다면
컴파일시 오류를 내줬으면 합니다. ㅠ.ㅠ

근데 요즘 컴파일러도 main() {}가 통용되나요?
한번 해봐야징... =3=3

바라미의 이미지

...
C 에서는 반환형식이 선언되어있지 않으면 int 가 생략되어있는 것으로간주합니다.
main 도 마찬가지고요.
고로 반환 형식을 지정해 주지 않은 main 에서 return 안해주면..
반환 안해줬다고 오류를 내는거고요..
반환형식이 없으면 무조건 int 라고 보시면 됩니다...
그리고.. 제가 알기론..
int main() 이 더 낫지 않을까요.

책에 나온대로라면..
return 1 해주면 프로그램이 비정상 종료 ㅤㄷㅚㅆ다는 표시로 된다고 알고 있습니다..
0 은 아무이상 없다는 것이고..
특히 유닉스,리눅스의 경우 리턴된 에러 표식으로.. 쉘프로그래밍을 이용하는 방법도 있고..

stdlib.h 를 인클루드 하시면 EXIT_SUCCESS 와 EXIT_FAILURE 매크로가 있는걸로 압니다..
각각 return EXIT_SUCCESS; 이렇게 사용하는걸로요..

GunSmoke의 이미지

GunSmoke wrote:

그러나 이러한 gcc의 진단 메시지는 오해의 소지가 있습니다. 실재 암시적 선언이 발생하는 때는 init()를 호출하는 순간이고 암시적 선언이 사라지는 순간은 함수 본체를 구성하는 블럭이 끝나는 곳, 즉 6행이라는 것입니다. 따라서 8행에서 실재 init의 함수 정의가 나타나더라도 이미 암시적 선언이 통용범위에서 사라진 이후이므로 구현체는 init()의 함수 호출이 실제 정의된 함수의 데이터형과 호환되지 않는다는 사실을 알지 못하고 잘못된 프로그램을 성공적으로 컴파일할 수 있다는 것입니다.

위 내용은 한빛미디어에서 출간된 C 펀더멘탈에서 참고했습니다.

大逆戰

pynoos의 이미지

말씀하시는 요지가

"암묵적 형선언의 유효성은 함수정의 범위인데, 경고로 인해 파일 범위로 오해시킬 수 있다"

인가요?

GunSmoke의 이미지

pynoos wrote:
말씀하시는 요지가

"암묵적 형선언의 유효성은 함수정의 범위인데, 경고로 인해 파일 범위로 오해시킬 수 있다"

인가요?

그렇습니다만... 복잡하게 썼나요?

大逆戰

doldori의 이미지

GunSmoke wrote:
pynoos wrote:
말씀하시는 요지가

"암묵적 형선언의 유효성은 함수정의 범위인데, 경고로 인해 파일 범위로 오해시킬 수 있다"

인가요?

그렇습니다만... 복잡하게 썼나요?


저도 무슨 뜻인지 잘 이해하지 못했는데요... ^^;
dummy.c:9: warning: type mismatch with previous implicit declaration
이 메시지는 4행에서의(previous) 암시적 선언과 현재(9행)의 함수 정의가
일치하지 않는다는 뜻이라고 이해했는데, 메시지 자체는 별 문제가 없지 않나요?
그것보다 경고로 그치는 것이 마음에 들지 않습니다.
참고로 제가 쓰고 있는 gcc 3.4.2는 -std=c89 옵션에서도 에러를 내는군요.
GunSmoke의 이미지

doldori wrote:
dummy.c:9: warning: type mismatch with previous implicit declaration
이 메시지는 4행에서의(previous) 암시적 선언과 현재(9행)의 함수 정의가
일치하지 않는다는 뜻이라고 이해했는데, 메시지 자체는 별 문제가 없지 않나요?
그것보다 경고로 그치는 것이 마음에 들지 않습니다.
참고로 제가 쓰고 있는 gcc 3.4.2는 -std=c89 옵션에서도 에러를 내는군요.

위 진단 메시지가 9행을 지적하고 있기 때문에 문제가 되는 것입니다. 실재 '암시적 선언'의 정의를 고려했다면 gcc의 진단메시지는 6행을 지적했어야 했을 것입니다.

大逆戰

GunSmoke의 이미지

그나저나... 제 의사소통 능력을 의심해봐야겠습니다.

大逆戰

prio의 이미지

GunSmoke wrote:

001          #include <stdlib.h>
002          int main()
003          {
004               init();
005               exit(0);
006          }
007
008          void init()
009          {}

% gcc dummy.c -o dummy -warn -Wall
dummy.c: In function 'main' :
dummy.c:4: warning: implicit declaration of function 'init'
dummy.c: At top level:
dummy.c:9: warning: type mismatch with previous implicit declaration
dummy.c:4: warning: previous implicit declaration of 'init'
dummy.c:8: warning: 'init' was previously implicitly declared to return 'init'

흠. 제 생각엔 별 문제가 없어보이는걸요;;
이유로는..

1. 암시적 선언이 file-scope이라면 함수 정의와 type conflict이므로 warning이 아니라 error가 나야 한다. warning이 나고 있으므로 scope이 file-scope이 아니라는 걸 알 수 있다.
2. 9행은 파일의 끝부분이 아니라 function definition이 parser에 의해 해석된 지점이다. (block이 시작되는 지점, '{'이 등장한 지점) 즉, 해당 warning은 '암시적 선언'이 아니라, '함수 정의'에 대한 것이다.

사족: parser의 입장에서, 마지막 warning이 8행을 가리키는 건 좀 어색해 보이는데요;; 9행이면 모를까.. 신경을 좀 많이 쓰면 8행을 가리킬 수도 있겠네요 ㅎㅎ

GunSmoke의 이미지

prio wrote:

1. 암시적 선언이 file-scope이라면 함수 정의와 type conflict이므로 warning이 아니라 error가 나야 한다. warning이 나고 있으므로 scope이 file-scope이 아니라는 걸 알 수 있다.
2. 9행은 파일의 끝부분이 아니라 function definition이 parser에 의해 해석된 지점이다. (block이 시작되는 지점, '{'이 등장한 지점) 즉, 해당 warning은 '암시적 선언'이 아니라, '함수 정의'에 대한 것이다.

사족: parser의 입장에서, 마지막 warning이 8행을 가리키는 건 좀 어색해 보이는데요;; 9행이면 모를까.. 신경을 좀 많이 쓰면 8행을 가리킬 수도 있겠네요 ㅎㅎ

prio님의 말씀이 옳았습니다. 예제를 다음과 같이 바꿔 테스트했습니다.

      1 #include <stdlib.h>
      2 int main()
      3 {
      4         init();
      5         exit(0);
      6 }
      7
      8 void init()
      9 {
     10 }

결과는

dummy.c:9: warning: type mismatch with previous implicit declaration
dummy.c:4: warning: previous implicit declaration of `init'
dummy.c:9: warning: `init' was previously implicitly declared to return `int'

따라서 함수 init가 정의되는 순간은 첫번째 '{ '가 나오는 순간이라고 할 수 있습니다.

엄청난 오류를 저지를 뻔 했습니다. 이 글을 읽으셨던 모든 분들께 용서를 구합니다. 개인적으로 잘 알지도 못하는 지식을 마치 옳은 것인양 떠들어대는 태도를 경멸하는데 제 스스로 이런 짓을 하는걸 보면... 너무나 부끄럽습니다.

ps. prio님의 말씀대로 제가 가장 처음에 제시했던 예제의 컴파일 결과 역시 위와 같았습니다. 책이 집필될 당시에 비해 gcc의 진단메시지가 더욱 발전했음을 알 수 있습니다.

大逆戰

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.