LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1653|回复: 29

Gentoo 目前 stable 的 GCC 可能存在 BUG!

[复制链接]
发表于 2009-12-2 23:42:54 | 显示全部楼层 |阅读模式
test.c
  1. #include <stdio.h>
  2. #include <linux/types.h>

  3. #define UNIT_BITS       32

  4. struct data {
  5.         __u32 d3;
  6.         __u32 d2;
  7.         __u32 d1;
  8.         __u32 d0;
  9. };

  10. static inline void
  11. data_set_hard (struct data *ret,
  12.                __u32 a, __u32 b, __u32 c, __u32 d)
  13. {
  14.         ret->d3 = a;
  15.         ret->d2 = b;
  16.         ret->d1 = c;
  17.         ret->d0 = d;
  18. }

  19. static inline void
  20. data_set (struct data *ret, int bit)
  21. {
  22.         __u32 *data[4];
  23.         int a, b;

  24.         a = bit / UNIT_BITS;
  25.         b = bit % UNIT_BITS;

  26.         data[0] = &ret->d0;
  27.         data[1] = &ret->d1;
  28.         data[2] = &ret->d2;
  29.         data[3] = &ret->d3;

  30.         *data[a] |= 1 << b;
  31. }

  32. int
  33. main (void)
  34. {
  35.         struct data test = {0};
  36.         int i;

  37.         data_set_hard(&test, 0, 0, 0, 0);

  38.         for (i=0; i<UNIT_BITS*4; i++) {
  39.                 data_set(&test, i);
  40.         }

  41.         printf ("test = %.8x, %.8x, %.8x, %.8x\n",
  42.                 test.d3, test.d2, test.d1, test.d0);

  43.         return 0;
  44. }
复制代码

用 gcc -O2 -Wall -o test test.c 编译一下
如果运行结果是 test = ffffffff, ffffffff, ffffffff, ffffffff 则证明你的 gcc 没有问题
如果运行结果是 test = 00000000, 00000000, 00000000, ffffffff 则证明存在 BUG

请测试的朋友们贴出你们的 gcc -v 信息和运行结果
发表于 2009-12-2 23:58:34 | 显示全部楼层
看得一头雾水。能测出什么“问题”?
  1. $ gcc -Wall -o test test.c; ./test
  2. test = ffffffff, ffffffff, ffffffff, ffffffff
  3. $ gcc -O2 -Wall -o test test.c; ./test
  4. test = 00000000, 00000000, 00000000, ffffffff
复制代码

gcc 的信息:
  1. $ gcc -v
  2. Using built-in specs.
  3. Target: i686-pc-linux-gnu
  4. Configured with: /var/tmp/portage/sys-devel/gcc-4.3.4/work/gcc-4.3.4/configure --prefix=/usr --bindir=/usr/i686-pc-linux-gnu/gcc-bin/4.3.4 --includedir=/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include --datadir=/usr/share/gcc-data/i686-pc-linux-gnu/4.3.4 --mandir=/usr/share/gcc-data/i686-pc-linux-gnu/4.3.4/man --infodir=/usr/share/gcc-data/i686-pc-linux-gnu/4.3.4/info --with-gxx-include-dir=/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4 --host=i686-pc-linux-gnu --build=i686-pc-linux-gnu --disable-altivec --disable-fixed-point --enable-nls --without-included-gettext --with-system-zlib --disable-checking --disable-werror --enable-secureplt --disable-multilib --enable-libmudflap --disable-libssp --enable-libgomp --enable-java-awt=gtk --with-arch=i686 --enable-languages=c,c++,java,treelang,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.3.4 p1.0, pie-10.1.5'
  5. Thread model: posix
  6. gcc version 4.3.4 (Gentoo 4.3.4 p1.0, pie-10.1.5)
复制代码
回复 支持 反对

使用道具 举报

发表于 2009-12-3 00:04:50 | 显示全部楼层
搞错了,结果同楼上。。。。
$gcc -v
Reading specs from /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/specs
Target: x86_64-pc-linux-gnu
Configured with: /var/tmp/portage/sys-devel/gcc-4.3.4/work/gcc-4.3.4/configure --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/4.3.4 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.3.4 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.3.4/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.3.4/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/include/g++-v4 --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --disable-altivec --disable-fixed-point --disable-nls --with-system-zlib --disable-checking --disable-werror --enable-secureplt --disable-multilib --enable-libmudflap --disable-libssp --enable-libgomp --disable-libgcj --enable-languages=c,c++,treelang --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.3.4 p1.0, pie-10.1.5'
Thread model: posix
gcc version 4.3.4 (Gentoo 4.3.4 p1.0, pie-10.1.5)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-12-3 00:10:43 | 显示全部楼层
看来真的 gentoo 里的 4.3.x gcc 有问题
我用 4.1.2 和 4.4.2 就没事,都是 ffffffff

这其实是 -O2 优化参数与 inline 函数之间冲突的一个 BUG
回复 支持 反对

使用道具 举报

发表于 2009-12-3 01:41:11 | 显示全部楼层
我觉得可能和指针有关……
我这里没有4.3的,lz试试这样还有问题不?

  1. switch (a)
  2. {
  3. case 0: ret->d0 |= 1 << b; break;
  4. case 1: ret->d1 |= 1 << b; break;
  5. case 2: ret->d2 |= 1 << b; break;
  6. case 3: ret->d2 |= 1 << b; break;
  7. default: break;
  8. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2009-12-3 05:03:33 | 显示全部楼层
Post by platinum;2051887
看来真的 gentoo 里的 4.3.x gcc 有问题
我用 4.1.2 和 4.4.2 就没事,都是 ffffffff

这其实是 -O2 优化参数与 inline 函数之间冲突的一个 BUG

我在debian和gentoo中都测试了, debian是gcc4.3.1
gentoo是gcc4.3.4
结果都是加了优化参数结果不正确.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-12-3 09:32:01 | 显示全部楼层
Post by Etrnls;2051905
我觉得可能和指针有关……
我这里没有4.3的,lz试试这样还有问题不?

  1. switch (a)
  2. {
  3. case 0: ret->d0 |= 1 << b; break;
  4. case 1: ret->d1 |= 1 << b; break;
  5. case 2: ret->d2 |= 1 << b; break;
  6. case 3: ret->d2 |= 1 << b; break;
  7. default: break;
  8. }
复制代码


不是代码的问题,因为
1、我在 4.1.2、4.4.2 以及 3.2.3 都试过,没有问题
2、在 4.3 上如果不加 -O2 或换成 -O1 就问题
3、如果函数不用 inline 也没问题
4、更蹊跷的,在 *data[a] |= 1 << b; 后面加个 printf ("."); 在 4.3 中编译都没有问题
回复 支持 反对

使用道具 举报

发表于 2009-12-3 13:03:21 | 显示全部楼层
Post by platinum;2051932
不是代码的问题,因为
1、我在 4.1.2、4.4.2 以及 3.2.3 都试过,没有问题
2、在 4.3 上如果不加 -O2 或换成 -O1 就问题
3、如果函数不用 inline 也没问题
4、更蹊跷的,在 *data[a] |= 1 << b; 后面加个 printf ("."); 在 4.3 中编译都没有问题


误解了……我不是说代码有问题
我的感觉是由于那里面有指针,这个指针指向了其他某个变量的地址,也就是说同一个内存位置现在个可以被不止一种方式访问,所以造成了优化的时候出现了问题,我刚在别的机器上找了一个gcc-4.3.3,的确改成switch就不会出现优化错误了。
事实上不需要printf(".")就可以让结果正确,只要在每次data_set后面加上一行

  1. __asm__ __volatile__ ("":::"memory");
复制代码

就可以了
回复 支持 反对

使用道具 举报

发表于 2009-12-3 13:12:57 | 显示全部楼层
Post by Etrnls;2051982
误解了……我不是说代码有问题
我的感觉是由于那里面有指针,这个指针指向了其他某个变量的地址,也就是说同一个内存位置现在个可以被不止一种方式访问,所以造成了优化的时候出现了问题,我刚在别的机器上找了一个gcc-4.3.3,的确改成switch就不会出现优化错误了。
事实上不需要printf(".")就可以让结果正确,只要在每次data_set后面加上一行

  1. __asm__ __volatile__ ("":::"memory");
复制代码

就可以了


简单看了一下,开了O2以后传给printf的参数前三个都是直接传的立即数0,也就是gcc认为test这个变量没被修改,所以直接常量传播到了printf的参数,(但是为什么第四个是正确的-_-|||,我再研究研究……)所以上面那句话可以从循环里面拿出来放在printf前面,结果就正确了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-12-3 14:07:16 | 显示全部楼层
Etrnls 兄说的内嵌空汇编方式的确可行
真是挺奇怪的,不知道 GNU 官方是否知道这个 BUG,但从 4.4 的表象上看,没有这个问题,是不是已经修正了?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表