3

なぜこれが機能するのか驚いていますか?

short main [] ={};

これはファイル内の唯一のコンテンツです。gccで正しくコンパイルされます。しかし、実行すると、セグメンテーション違反が出力されます。mainの名前を変更すると、コンパイラでエラーが発生します。誰かがここで何が起こっているのか私に説明できますか?

4

3 に答える 3

4

明らかに、リンカはグローバルオブジェクトのタイプ(変数や関数など)を認識していませんが、アドレスのみを認識しています。したがって、変数が関数であるかのようにプログラムをリンクします。明らかな理由でクラッシュします。

于 2010-09-01T13:05:47.377 に答える
3

このようなエラーが発生していますか?

Undefined symbols:
  "_main", referenced from:
      start in crt1.10.6.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

これはコンパイラ エラーではなく、リンカ エラーです。

コンパイルでは、各ソース ファイルがオブジェクト ファイルに変換されます。

int main()プログラムが複数のソースで構成されている可能性がありmain()、これらのソースの 1 つだけで定義されているか、存在する必要さえない (動的ライブラリなど)ため、存在するかどうかのチェックはありません。ソースから

short main[] = {};

コンパイラによって有効な宣言 (short名前付きのグローバル配列を作成mainし、空の配列に初期化する) と見なされるため、エラーは生成されません。

存在するかどうかの検出はint main()、リンカによってチェックされます。リンカーは、コンパイルされたオブジェクト ファイルを実行可能な実行可能ファイルにバインドします。リンカがシンボルを見つけられない場合、main上で説明したようなエラーが発生します。残念ながら、従来の C ABI は、関数やエクスポートされた変数の種類を区別していません。したがって、mainが配列として宣言されていても、リンカは「呼び出されたものmainが存在する」ことしか認識しておらず、それ以上チェックできないため、同様にパスします。

その結果、間違った書き方をしているにもかかわらず、プログラムはエラーなく生成されます。

プログラムが実行されると、いわゆるmain実行可能コードは保持されません。むしろ、それは単なるデータです (ゼロ化されている可能性があります)。したがって、システムは予期しないことを行う可能性があります(あなたの場合、それはSEGFAULTです)。

-Wallこれは、gcc でフラグを使用してコンパイルするときに実際にキャッチされる可能性があり、警告が表示されます。

<stdin>:1: warning: ‘main’ is usually a function
于 2010-09-01T13:15:10.360 に答える
1

より多くのオプションでコンパイルしてみてください。:)

たとえば、単純な-Wallを追加します

gcc -Wall test.c -o t
test.c:1: warning: ‘main’ is usually a function

関連する標準ページを読んだことはありませんが、コンパイルするには、必ずしも関数ではなく、何らかのメインが必要なようです...

于 2010-09-01T13:09:07.677 に答える