免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 4533 | 回复: 23
打印 上一主题 下一主题

还是C经典错误!!! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-11-15 02:25 |只看该作者 |倒序浏览
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
2 [报告]
发表于 2006-11-15 02:39 |只看该作者
gcc 版本 4.1.0 +FedoraCore5
程序陷入了死循环

论坛徽章:
0
3 [报告]
发表于 2006-11-15 11:17 |只看该作者
编译的时候,是不是用了优化了?试试不加优化看看。。
另外,i前加volatile,定义i为内存变量

论坛徽章:
0
4 [报告]
发表于 2006-11-15 15:35 |只看该作者
原帖由 greensky_34 于 2006-11-15 02:25 发表
看到《C陷阱与缺陷》上讲的

[code]#include <stdio.h>

int main (int argc, char *argv[]){
        int i = 5;
        int a[10];

        for(i=0; i<=10; i++){
                a = 0;
        }
        return 0;
}
[/co ...


这只能说明你测试用的编译器不是“按照内存递减方式分配内存的的编译器”。

我想对于“按照内存递减方式分配内存的的编译器”,能够产生死循环的原因是:
a[10](显然内存越界了)的内存空间和 i 的内存空间是同一块空间。所以会死循环。。

论坛徽章:
0
5 [报告]
发表于 2006-11-15 15:39 |只看该作者
原帖由 greensky_34 于 2006-11-15 02:25 发表
看到《C陷阱与缺陷》上讲的

[code]#include <stdio.h>

int main (int argc, char *argv[]){
        int i = 5;
        int a[10];

        for(i=0; i<=10; i++){
                a = 0;
        }
        return 0;
}
[/co ...


g++-4.1会死循环

论坛徽章:
0
6 [报告]
发表于 2006-11-15 18:57 |只看该作者
bash-2.05$ gcc -o pgO2 -O2 pg.c
bash-2.05$ time ./pgO2

real    0m0.015s
user    0m0.000s
sys     0m0.010s
bash-2.05$ gcc -o pgO0 -O0 pg.c
bash-2.05$ time ./pgO0
^C

real    0m6.023s
user    0m5.928s
sys     0m0.009s
bash-2.05$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-unknown-openbsd3.0/2.95.3/specs
gcc version 2.95.3 20010125 (prerelease)
bash-2.05$ gcc -c -o pgO0.o -O0 pg.c
bash-2.05$ gcc -c -o pgO2.o -O2 pg.c
bash-2.05$ objdump -S pgO0.o pgO2.o

pgO2.o:     file format a.out-i386-netbsd

Disassembly of section .text:

00000000 <_main>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 38                sub    $0x38,%esp
   6:   e8 f5 ff ff ff          call   0 <_main>
   b:   b9 0a 00 00 00          mov    $0xa,%ecx
  10:   89 e8                   mov    %ebp,%eax
  12:   90                      nop
  13:   90                      nop
  14:   c7 00 00 00 00 00       movl   $0x0,(%eax)
  1a:   83 c0 fc                add    $0xfffffffc,%eax
  1d:   49                      dec    %ecx
  1e:   79 f4                   jns    14 <_main+0x14>
  20:   31 c0                   xor    %eax,%eax
  22:   c9                      leave
  23:   c3                      ret
        ...

pgO0.o:     file format a.out-i386-netbsd

Disassembly of section .text:

00000000 <_main>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 38                sub    $0x38,%esp
   6:   e8 f5 ff ff ff          call   0 <_main>
   b:   c7 45 fc 05 00 00 00    movl   $0x5,0xfffffffc(%ebp)
  12:   c7 45 fc 00 00 00 00    movl   $0x0,0xfffffffc(%ebp)
  19:   90                      nop
  1a:   90                      nop
  1b:   90                      nop
  1c:   83 7d fc 0a             cmpl   $0xa,0xfffffffc(%ebp)
  20:   7e 02                   jle    24 <_main+0x24>
  22:   eb 1c                   jmp    40 <_main+0x40>
  24:   8b 45 fc                mov    0xfffffffc(%ebp),%eax
  27:   89 c2                   mov    %eax,%edx
  29:   8d 04 95 00 00 00 00    lea    0x0(,%edx,4),%eax
  30:   8d 55 d4                lea    0xffffffd4(%ebp),%edx
  33:   c7 04 10 00 00 00 00    movl   $0x0,(%eax,%edx,1)
  3a:   ff 45 fc                incl   0xfffffffc(%ebp)
  3d:   eb dd                   jmp    1c <_main+0x1c>
  3f:   90                      nop
  40:   31 c0                   xor    %eax,%eax
  42:   eb 00                   jmp    44 <_main+0x44>
  44:   c9                      leave
  45:   c3                      ret

bash-2.05$


前者看起来没什么异常,后者按了 CTRL-C 结束,显然是用户终止,而非自主退出。
下面再看看在 CYGWIN_NT-5.0 上的表现:

langue@moon /cygdrive/z/moon/langue/.tmp
$ gcc -o pgO0 pg.c

langue@moon /cygdrive/z/moon/langue/.tmp
$ gcc -o pgO2 pg.c

langue@moon /cygdrive/z/moon/langue/.tmp
$ time ./pgO0

real    0m0.024s
user    0m0.030s
sys     0m0.010s

langue@moon /cygdrive/z/moon/langue/.tmp
$ time ./pgO2

real    0m0.022s
user    0m0.020s
sys     0m0.020s

langue@moon /cygdrive/z/moon/langue/.tmp
$ gcc -v
Reading specs from /bin/../lib/gcc/i686-pc-cygwin/3.4.4/specs
Configured with: /gcc/gcc-3.4.4/gcc-3.4.4-1/configure --verbose --prefix=/usr --
exec-prefix=/usr --sysconfdir=/etc --libdir=/usr/lib --libexecdir=/usr/lib --man
dir=/usr/share/man --infodir=/usr/share/info --enable-languages=c,ada,c++,d,f77,
java,objc --enable-nls --without-included-gettext --enable-version-specific-runt
ime-libs --without-x --enable-libgcj --disable-java-awt --with-system-zlib --ena
ble-interpreter --disable-libgcj-debug --enable-threads=posix --enable-java-gc=b
oehm --disable-win32-registry --enable-sjlj-exceptions --enable-hash-synchroniza
tion --enable-libstdcxx-debug : (reconfigured)
Thread model: posix
gcc version 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125)

langue@moon /cygdrive/z/moon/langue/.tmp
$ gcc -c -o pgO0.o -O0 pg.c

langue@moon /cygdrive/z/moon/langue/.tmp
$ gcc -c -o pgO2.o -O2 pg.c

langue@moon /cygdrive/z/moon/langue/.tmp
$ objdump -S pgO0.o pgO2.o

pgO0.o:     file format pe-i386

Disassembly of section .text:

00000000 <_main>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 58                sub    $0x58,%esp
   6:   83 e4 f0                and    $0xfffffff0,%esp
   9:   b8 00 00 00 00          mov    $0x0,%eax
   e:   83 c0 0f                add    $0xf,%eax
  11:   83 c0 0f                add    $0xf,%eax
  14:   c1 e8 04                shr    $0x4,%eax
  17:   c1 e0 04                shl    $0x4,%eax
  1a:   89 45 b4                mov    %eax,0xffffffb4(%ebp)
  1d:   8b 45 b4                mov    0xffffffb4(%ebp),%eax
  20:   e8 00 00 00 00          call   25 <_main+0x25>
  25:   e8 00 00 00 00          call   2a <_main+0x2a>
  2a:   c7 45 f4 05 00 00 00    movl   $0x5,0xfffffff4(%ebp)
  31:   c7 45 f4 00 00 00 00    movl   $0x0,0xfffffff4(%ebp)
  38:   83 7d f4 0a             cmpl   $0xa,0xfffffff4(%ebp)
  3c:   7f 12                   jg     50 <_main+0x50>
  3e:   8b 45 f4                mov    0xfffffff4(%ebp),%eax
  41:   c7 44 85 b8 00 00 00    movl   $0x0,0xffffffb8(%ebp,%eax,4)
  48:   00
  49:   8d 45 f4                lea    0xfffffff4(%ebp),%eax
  4c:   ff 00                   incl   (%eax)
  4e:   eb e8                   jmp    38 <_main+0x38>
  50:   b8 00 00 00 00          mov    $0x0,%eax
  55:   c9                      leave
  56:   c3                      ret
  57:   90                      nop
  58:   90                      nop
  59:   90                      nop
  5a:   90                      nop
  5b:   90                      nop
  5c:   90                      nop
  5d:   90                      nop
  5e:   90                      nop
  5f:   90                      nop

pgO2.o:     file format pe-i386

Disassembly of section .text:

00000000 <_main>:
   0:   55                      push   %ebp
   1:   b8 10 00 00 00          mov    $0x10,%eax
   6:   89 e5                   mov    %esp,%ebp
   8:   83 ec 38                sub    $0x38,%esp
   b:   83 e4 f0                and    $0xfffffff0,%esp
   e:   e8 00 00 00 00          call   13 <_main+0x13>
  13:   e8 00 00 00 00          call   18 <_main+0x18>
  18:   31 c0                   xor    %eax,%eax
  1a:   8d b6 00 00 00 00       lea    0x0(%esi),%esi
  20:   31 d2                   xor    %edx,%edx
  22:   89 54 85 c8             mov    %edx,0xffffffc8(%ebp,%eax,4)
  26:   40                      inc    %eax
  27:   83 f8 0a                cmp    $0xa,%eax
  2a:   7e f4                   jle    20 <_main+0x20>
  2c:   c9                      leave
  2d:   31 c0                   xor    %eax,%eax
  2f:   c3                      ret

langue@moon /cygdrive/z/moon/langue/.tmp
$


显然,在这里并没有表现出异常。

 

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
7 [报告]
发表于 2006-11-15 19:02 |只看该作者
和如何编译有关。

如果没有优化,没有浪费,那么因为a[10]访问越界,其实访问的是i,在最后又将i重置为0,导致i一直小于等于10。

论坛徽章:
0
8 [报告]
发表于 2006-11-15 19:14 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
9 [报告]
发表于 2006-11-15 19:24 |只看该作者
编译器的行为,一定和优化有关,就是还不清楚 i 和 temp 的先后顺序,编译器(优化和不优化)分别是怎样处理的。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
10 [报告]
发表于 2006-11-15 19:58 |只看该作者
原帖由 langue 于 2006-11-15 19:24 发表
编译器的行为,一定和优化有关,就是还不清楚 i 和 temp 的先后顺序,编译器(优化和不优化)分别是怎样处理的。


temp,没temp啊。^_^。

i总是会在a的高地址的。这就是栈的结构。

一般的编译器都会在i和a之间留有空间。

“理想”的编译器就不加空隙。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP