这些天我在C中找到了一个提到中止功能的博客。
以下是中止功能的源代码: http://cristi.indefero.net/p/uClibc-cristi/source/tree/0_9_14/libc/stdlib/abort.c
我发现它使用hlt
指令(我的电脑是x86)。
但似乎hlt
必须在第0环中运行。
(参考维基http://en.wikipedia.org/wiki/HLT)
似乎中止正在用户空间中运行。因此,在中止中使用hlt
指令似乎是非法的。
BTW,我尝试在linux和windows中运行hlt
。但我遇到了错误。
在linux中:
#include <iostream>
using namespace std;
#define HLT_INST asm("hlt")
int main(){
cout<<"whill run halt"<<endl;
HLT_INST; //result in SIGSEGV error
return 0;
}
在Windows中:
cout<<"will run hlg"<<endl;
/*Unhandled exception at 0x0040101d in test_learn.exe: 0xC0000096: Privileged instruction.
*/
__asm{
hlt;
}
答案 0 :(得分:6)
abort
函数仅在发送hlt
失败后才使用SIGABRT
指令。如果您阅读源代码,该函数首先尝试:
raise(SIGABRT);
然后调用无效指令:
/* Still here? Try to suicide with an illegal instruction */
if (been_there_done_that == 2) {
been_there_done_that++;
ABORT_INSTRUCTION;
}
所以你是对的,hlt
需要第0个特权。这正是使它成为无效指令的原因。执行它会调用一个无效的指令处理程序,在你的情况下(我想)SIGSEGV。
答案 1 :(得分:3)
您可能需要查看SIGABRT POSIX信号
例如,如果您在使用GDB进行调试时遇到abort()
来电,则会看到:
Program received signal SIGABRT, Aborted.
0x0000003c47e352d5 in raise () from /lib64/libc.so.6
(gdb) where
#0 0x0000003c47e352d5 in raise () from /lib64/libc.so.6
#1 0x0000003c47e36beb in abort () from /lib64/libc.so.6
#2 0x0000000000400721 in main (argc=1, argv=0x7fffffffde18) at test.c:27
正如@kbok所提到的,abort
函数的反汇编包括hlt
指令:
(gdb) disassemble abort
Dump of assembler code for function abort:
...
0x0000003c47e36b08 <+152>: hlt
...
(但确实SEGFAULT indeed
)
(gdb) break *0x0000003c47e36b08
Breakpoint 2 at 0x3c47e36b08
(gdb) jump *0x0000003c47e36b08
Breakpoint 2, 0x0000003c47e36b08 in abort () from /lib64/libc.so.6
(gdb) next
Single stepping until exit from function abort,which has no line number information.
Program received signal SIGSEGV, Segmentation fault.
0x0000003c47e36b08 in abort () from /lib64/libc.so.6