gpt4 book ai didi

c - GCC 优化器的未初始化警告

转载 作者:太空宇宙 更新时间:2023-11-04 04:04:26 25 4
gpt4 key购买 nike

我用 C 实现了一棵树,现在我想定义一个包装树集。我的树在 tree.h 中有一个迭代器:

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 编译它,没有任何警告。对于我的树集,我在 tset.h 中定义了我的树集迭代器,如下所示:

typedef struct tset_t tset_t;

typedef struct tset_iter_t {
tree_iter_t iter;
} tset_iter_t;

以及在 tset.c 中获取它的函数。

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 时,我得到一个返回语句警告: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 行左右的汇编代码(只是调用树函数的通常函数调用开销)。 gcc -O2 -S -combine tset.c tree.c 给了我警告,内联滴定器,并产生了这个:

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 在第一种情况下优化(或分析)什么,为什么给我警告?

谢谢。

最佳答案

我认为这个警告是一个错误。你用的是哪个 gcc?当我使用 gcc 4.0 和 4.2 编译(公认的单个文件)时,不会发生这种情况。

这是优化汇编程序的注释版本。我在这里看不到任何未分配的东西,这就是为什么我认为警告不正确的原因。我猜到了树结构。

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

编辑:请注意,编译器小心地保留了 tree_iter_t.info 中随机未初始化垃圾的高 6 位。

关于c - GCC 优化器的未初始化警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7857816/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com