は、以下のコードを検討:x86のためのものであるとしてコンパイルなぜGCCは異なるスコープのローカルユニオンに別々のスタックスペースを割り当てるのですか?
#include <stdlib.h>
#ifndef TRY
#define TRY struct
#endif
TRY testme
{
int one;
int two;
char three;
int four;
};
int
main (void)
{
{
volatile TRY testme one;
one.one = 2;
one.three = 7;
}
{
volatile TRY testme twos;
twos.one = 3;
}
{
volatile TRY testme one;
one.one = 4;
}
{
volatile TRY testme twos;
twos.one = 5;
}
{
volatile TRY testme twos;
twos.one = 6;
}
{
volatile TRY testme twos;
twos.one = 6;
}
return EXIT_SUCCESS;
}
は(意味testmeが構造体である)であり、コンパイラは主に割り当てるスタックサイズは16バイトです。
$ gcc -g -O2 test.c -o test
$ objdump -d ./test | ./checkstack.pl i386 | grep main
16 main
しかし、(testmeが組合であることを意味する)組合に定義TRYでコンパイルされ、コンパイラは主に割り当てるスタックサイズは32バイトである:また
$ gcc -DTRY=union -g -O2 test.c -o test
$ objdump -d ./test | ./checkstack.pl i386 | grep main
、構造体の任意の追加のインスタンス追加のスコープで定義された/共用体は、共用体を使用するときより大きなスタック割り当てを生成しますが、構造体として使用されるときはスタック割り当てを拡大しません。
これは意味をなさない - ユニオンはスタック領域を減らす必要はありません。それ以上の場合は、同じフィールドを持つ構造体です。
GCCは異なるスコープであっても同時に使用されているように見えるが、構造体では同じことをしないように見える。
いくつかのより多くの明確化:
揮発性は、割り当てを離れて最適化から、コンパイラを停止するために使用されます。 volatileを取り除き、最適化を行わずにコンパイルすると同じ結果が得られます。
testmeがメンバの1つとして共用体を持つ構造体であっても、同じ動作が観察されます。言い換えれば、構造体のメンバの1つがGCCのスタック割り当てのための共用体であれば十分です。
コンパイラはgccバージョン4.4.3(Ubuntu 4.4.3-4ubuntu5)ですが、他のアーキテクチャ用の他のGCCバージョンも同じ動作を示しました。
checkstack.plは、スタックを割り当てるために使用される命令(スタックポインタへのサブ)のobjdump出力を単に検索します。
私の質問:
- なぜGCCがこれを行うのですか?これはバグですか、この動作の理由はありますか?
- これはバグではないと仮定して、これを回避し、GCCに構造体のスタックをユニオンと同じように割り当てる方法があります。
明確化:構造体または共用体は、その部分のサイズからサイズが大きくなるように見えるなぜ私の質問はありません。私は理由が整列のためのパディングであることを理解します。私の問題は、コンパイラは異なるスコープで定義されているにもかかわらず、同じフィールドを持つ構造体では同じことをしないにもかかわらず、複数のスタックフレームを複数のスタックのインスタンスに割り当てることです。
ありがとうございます!
はたぶん組合は、同様に(まだ) '-O2'で最適化されていませんか?生成されたアセンブラコードを見てください。また、 'strict-aliasing'を無効にしてみてください。ああ、現在のGCCを試してみてください。 –
[この質問](http://stackoverflow.com/questions/8453881/sizeof-union-larger-than-expected-how-does-type-alignment-take-place-here)と[この1つ](http://stackoverflow.com/questions/7212585/why-is-my-unions-size-bigger-than-i-expected)?それはパディングとアライメントの制約のようです。 – Coren
@ Anony-Mousse -fno-strict-aliasingは同じ結果をもたらします。私は最新のGCCをテストしてテストしています。 – gby