当前位置:  开发笔记 > 编程语言 > 正文

Unix表示怀疑 - 关于执行下面的程序

如何解决《Unix表示怀疑-关于执行下面的程序》经验,为你挑选了1个好方法。



1> SimonJ..:

当输入信号处理程序时,程序计数器(指向当前正在执行的指令的CPU寄存器)被保存在发生被零除的地方.忽略信号会将PC恢复到完全相同的位置,然后再次触发信号(并再次触发).

'x'的值或波动率与此无关 - 零已经转移到CPU寄存器中以准备执行除法.

man 2发出信号说明:

根据POSIX,在忽略不是由kill(2)或raise(3)函数生成的SIGFPE,SIGILL或SIGSEGV信号之后,进程的行为是未定义的.整数除零具有未定义的结果.在某些架构上,它将生成SIGFPE信号.(也将最负整数除以-1可能会生成SIGFPE.)忽略此信号可能会导致无限循环.

如果使用debug标志进行编译,我们可以在gdb中看到这个:

simon@diablo:~$ gcc -g -o sigtest sigtest.c 
simon@diablo:~$ gdb sigtest
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...

默认情况下,gdb不会将SIGINT传递给进程 - 更改此设置以便它看到第一个信号:

(gdb) handle SIGINT pass
SIGINT is used by the debugger.
Are you sure you want to change it? (y or n) y

Signal        Stop  Print   Pass to program Description
SIGINT        Yes   Yes Yes     Interrupt

我们走了:

(gdb) run
Starting program: /home/simon/sigtest 
x = 1
Hello World: 1

现在让我们打断它:

^C
Program received signal SIGINT, Interrupt.
0xb767e17b in nanosleep () from /lib/libc.so.6

继续分裂:

(gdb) cont
Continuing.
OUCH!  dividing by zero!
x = 0

Program received signal SIGFPE, Arithmetic exception.
0x0804853a in main () at sigtest.c:30
30              printf("Hello World: %d\n",1/x);

检查'x'的值,然后继续:

(gdb) print x
$1 = 0
(gdb) cont
Continuing.
FPE!  I got a signal: 8
psignal: Floating point exception

Program received signal SIGFPE, Arithmetic exception.
0x0804853a in main () at sigtest.c:30
30              printf("Hello World: %d\n",1/x);
(gdb) print x
$2 = 1

x显然现在是1,我们仍然有一个被零除 - 这是怎么回事?让我们检查底层汇编程序:

(gdb) disassemble 
Dump of assembler code for function main:
0x080484ca :    lea    0x4(%esp),%ecx
0x080484ce :    and    $0xfffffff0,%esp
...
0x08048533 :  mov    %eax,%ecx
0x08048535 :  mov    %edx,%eax
0x08048537 :  sar    $0x1f,%edx
0x0804853a :   idiv   %ecx           <<-- address FPE occurred at
0x0804853c :  mov    %eax,0x4(%esp)
0x08048540 :  movl   $0x8048653,(%esp)
0x08048547 :  call   0x8048384 
0x0804854c :  jmp    0x8048503 
End of assembler dump.

之后的一次Google搜索告诉我们,IDIV通过源操作数(ECX)划分EAX寄存器中的值.您可以猜测寄存器内容:

(gdb) info registers 
eax            0x1  1
ecx            0x0  0
...

推荐阅读
虎仔球妈_459
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有