2013-06-28 11 views
5

まず、状況をより正確に説明するためのより良いタイトルを見つけるのを手伝ってください。現実の(埋め込み)コードをデバッグする際に遭遇した次の単純化された問題のバージョンを作成しました。初期化されていない同じ名前のグローバル変数 - 奇妙なリンクの振る舞い

は、ファイルt1.cの次のコードを考えてみましょう:

#include <stdio.h> 

int A; 

void f() { printf("%d\n", A); } 

extern void g(); 

void main(void) 
{ 
    g(); A=1; g(); 
    A++; 
    f(); 
} 

t2.cのコード:

#include <stdio.h> 

double A; 

void g() 
{ 
    A += 1.0; 
    printf("%f\n", A); 
} 

さて、このようなコードをコンパイルして実行している:

gcc -Wall t1.c t2.c -o t && ./t 

を与えます
1.000000 
2.000000 
1 

両方のファイルには、異なるタイプのグローバル変数呼び出しAが含まれています。シンボルAは複数回存在するため、リンクエラーが予想されました。

は、私は実際に、私はそれらの両方を初期化し、私は二つの変数の1、エラー(複数の定義)を初期化(異なるの.oでオブジェクトサイズの変更)リンクの警告を取得します。

gcc 4.7と4.4で試しました。

これが期待どおりの動作ですか?もしそうなら、には私がtoolchain(gccベース)に警告するために何かできることがあります。

これはバグですか?

答えて

4

はい、リンカエラーを取得する-fno-commonオプションでコンパイル:あなたは1行でこれをコンパイルしたい場合は

$ gcc -Wall -fno-common -c t1.c 
$ gcc -Wall -fno-common -c t2.c 
$ gcc t1.o t2.o -o t 
t2.o:t2.c:(.bss+0x0): multiple definition of `_A' 
t1.o:t1.c:(.bss+0x0): first defined here 
collect2: error: ld returned 1 exit status 
$ 

あなたはまた、代わりにエラーを持っている--fatal-warningsとここ(リンカに--warn-commonを渡すことができます警告)のデフォルトgccにより

$ gcc -Wl,--fatal-warnings,--warn-common -Wall t1.c t2.c -o t 
/tmp/cc1xQo79.o: warning: common of `_A' overriding smaller common 
/tmp/ccLnhxoe.o: warning: smaller common is here 
collect2: error: ld returned 1 exit status 
$ 

は拡張としてC未定義の動作のさまざまな最適化を行います。 Cでは、そのようなプログラムの存在下で翻訳を停止することができます。ただし、あなたがそれを行うべき優れた理由がある場合を除いて、それを避けるべきです。

+0

答えてくれてありがとう:私は、初期化されていないグローバルがいわゆる* common * -blockに入ることに気づいていませんでした。 –

1

@ ouahさんの回答が却下されるのは、初期化されていない変数なので、それはただの警告だと思うので、.bssセクションに入ります。変数を初期化することによって、コンパイラはそれらを.dataセクションに移動させます - .bssが重複しているという事実はgccの奇妙なことかもしれません。

+0

セクションは重要ではありません:明示的にゼロで初期化された変数は、通常の定義(普通のものではありません)を作成しますが、 '.bss'で終わります。 – jilles