2011-10-22 12 views
1

Cでツリーを実装しましたが、今ではラッパーツリーセットを定義したいと考えています。私はtree.hの私のツリーのイテレータを持っている:GCCオプティマイザを使用した初期化されていない警告

typedef struct tree_iter_t { 
    void *current; 
    tree_t *tree; 
    unsigned char info : 2; 
} tree_iter_t; 

とtree.cでイテレータを取得するための機能:

tree_iter_t titerator(tree_t *t) { 
    tree_iter_t it; 
    it.current = t->min; 
    if (t->min) it.info = 0; 
    else it.info = 3; 
    it.tree = t; 
    return it; 
} 

私は警告なしで-Wall -O2でこれをコンパイルすることができます。

typedef struct tset_t tset_t; 

typedef struct tset_iter_t { 
    tree_iter_t iter; 
} tset_iter_t; 

とtset.c.でそれを取得する機能を次のように私の木のセットのために、私はtset.hの私のツリーセット・イテレータを定義し

struct tset_t { 
    tree_t *tree; 
}; 

tset_iter_t tsiterator(tset_t *ts) { 
    tset_iter_t it; 
    it.iter = titerator(ts->tree); 
    return it; 
} 

私はgcc -Wall -c -combine tset.c tree.cでコンパイルすると、私は問題がないが、私は-O2を追加するとき、私は、return文に警告を得る:warning: ‘it.iter.tree’ is used uninitialized in this functionを。なぜGCCはこれに問題がありますか?私は明白な何かを欠いていますかそれは私に初期化されて見えます。私は何が起こっていたかの感覚を取得しようとするgcc -S -O2 tset.cを走った、GCCは警告を与えておらず、これを生産:

tsiterator: 
pushl %ebp 
movl %esp, %ebp 
pushl %ebx 
subl $36, %esp 
movl 12(%ebp), %edx 
movl 8(%ebp), %ebx 
leal -20(%ebp), %eax 
movl (%edx), %edx 
movl %eax, (%esp) 
movl %edx, 4(%esp) 
call titerator 
movzbl -12(%ebp), %edx 
movzbl 8(%ebx), %eax 
andl $3, %edx 
andl $-4, %eax 
orl  %edx, %eax 
subl $4, %esp 
movb %al, 8(%ebx) 
movl -16(%ebp), %eax 
movl %eax, 4(%ebx) 
movl -20(%ebp), %eax 
movl %eax, (%ebx) 
movl %ebx, %eax 
movl -4(%ebp), %ebx 
leave 
ret $4 

私は、最適化は、いくつかの奇妙に見えるコードを生成することができます知っているが、一体何がここで起こっています! ?他のすべての(最適化された)ラッパー関数は、10-ishのアセンブリ行です(ツリーの関数を呼び出すための通常の関数呼び出しオーバーヘッド)。 gcc -O2 -S -combine tset.c tree.cは私に警告、インラインtiteratorを与え、これを生産:

tsiterator: 
pushl %ebp 
movl %esp, %ebp 
movl 12(%ebp), %edx 
pushl %ebx 
movl 8(%ebp), %eax 
movl (%edx), %ecx 
movl 4(%ecx), %edx 
movl %ecx, 4(%eax) 
cmpl $1, %edx 
movl %edx, (%eax) 
movzbl 8(%eax), %edx 
sbbl %ebx, %ebx 
andl $3, %ebx 
andl $-4, %edx 
orl  %ebx, %edx 
movb %dl, 8(%eax) 
popl %ebx 
popl %ebp 
ret $4 

私は実装を変更する場合:

tset_iter_t tsiterator(tset_t *ts) { 
    tset_iter_t it; 
    tree_iter_t i = titerator(ts->tree); 
    it.iter = i; 
    return it; 
} 

それは問題はなかったです。最初のケースでGCCの最適化(または解析)とは何ですか、なぜそれが私に警告を与えていますか?

ありがとうございました。

+0

'tree_iter_t it;'と 'it.tree = t;'です。 'it.tree'はどこですか?なぜ実際のコードを投稿していないのですか?最初のコードブロックの – cnicutar

+0

は、* t * treeであるべきですか? –

+0

Typo。それを私が直した。 – Nick

答えて

1

私はこの警告はバグだと思います。どのgccを使用していますか?私がgcc 4.0と4.2を使ってコンパイルすると(私には間違いなく1つのファイルを)コンパイルすると私には起こりません。

ここに最適化されたアセンブラの注釈付きバージョンがあります。ここに割り当てられていないものは私には見えないので、警告が正しいとは思わないのです。私は木構造について推測しました。

tsiterator: 
    pushl %ebp 
    movl %esp, %ebp 
    movl 12(%ebp), %edx ; edx has pointer to ts 
    pushl %ebx 
    movl 8(%ebp), %eax ; eax has pointer to retval 
    movl (%edx), %ecx ; ecx has ts->tree (?) 
    movl 4(%ecx), %edx ; edx has ts->tree->min (?) 
    movl %ecx, 4(%eax) ; store ts->tree into retval->iter->tree 
    cmpl $1, %edx  
    movl %edx, (%eax) ; store ts->tree->min into retval->iter->current 
    ;; This and the cmpl instruction above is all 
    ;; handling the bitmasking for retval->iter->info. 
    ;; Probably would be more efficient to not use a 
    ;; bit mask here, as the compiler could remove the 
    ;; second "and" and "or" instructions. 
    movzbl 8(%eax), %edx ; get current value of retval->iter->info 
    sbbl %ebx, %ebx ; ebx = 0 if unsigned edx < 1, else -1 
    andl $3, %ebx ; mask off new value    
    andl $-4, %edx ; mask off old value 
    orl  %ebx, %edx ; combine old | new  
    movb %dl, 8(%eax) ; store combined into retval->iter->info 
    popl %ebx 
    popl %ebp 
    ret $4 

EDIT:コンパイラは注意深くtree_iter_t.infoランダム初期化されていないジャンクの上位6ビットを保持することに留意されたいです。

+0

私はgcc 4.4.5 – Nick

0

gccがその特定のフィールドtreeについて不満を表明している理由がわかりませんでしたが、関数から戻ってきた構造の一部が初期化されていないことは間違いありません。実際には、基本的には常に変数の1つのフィールドを初期化し、他のフィールドは自動的に0で初期化する必要があります。

tree_iter_t it = { .tree = t }; 

と、あなたはその後もその場にassigmentをスキップすることがあります。あなたのケースで最も簡単にはC99の指定された初期化子を使用することです。

+0

を持っています "関数から戻ってくる構造体の一部は初期化されていません" - どの部分? – Nick

+0

@Nick、その部分の他のビットは 'info'やおそらく他のパディングに対応しています。 –

関連する問題