函数指针值的分段错误
Segmentation fault on value of function pointer
如果函数指针的值设置不正确,是否可以打开Segmentation Fault
?
或者 interpreter/compiler 会事先检测到吗?
void (*ptr)() = (void (*) ())0x0;
ptr();
没有什么能阻止你compiling/executing这样做,但肯定会失败。
详情取决于您使用的语言,但总的来说,这不仅是可能的,而且很有可能。
C 不提供任何保证。你可以说例如
#include <stddef.h>
typedef void (*foo)( void );
int main( void ) {
((foo)NULL)( );
return 0;
}
需要 NULL
,将其转换为一个函数并调用它(或至少尝试,然后崩溃。)在撰写本文时,gcc -Wall
和 clang -Wall
都不会即使是这种病态病例也不会检测或警告。
对于其他语言,可能会有更多的保护措施。但一般来说,不要指望你的程序能在错误的函数指针中幸存下来。
以下示例会产生您提到的分段错误:
int main(int argc, char *argv[]) {
void (*fun_ptr)() = (void (*)()) 1;
(*fun_ptr)();
return 0;
}
None of cc, clang, splint 发出警告。 C 假定程序员知道他在做什么。
更新
以下参考说明了为什么 C 允许通过指针访问绝对内存寻址。
Koenig, Andrew R., C Traps an Pitfalls,贝尔电话实验室,新泽西州默里山,技术备忘录,2.1。理解声明:
I once talked to someone who was writing a C program that was going to
run stand-alone in a small microprocessor. When this machine was
switched on, the hardware would call the subroutine whose address was
stored in location 0.
In order to simulate turning power on, we had to devise a C statement
that would call this subroutine explicitly. After some thought, we
came up with the following:
(*(void(*)())0)();
如果函数指针的值设置不正确,是否可以打开Segmentation Fault
?
或者 interpreter/compiler 会事先检测到吗?
void (*ptr)() = (void (*) ())0x0;
ptr();
没有什么能阻止你compiling/executing这样做,但肯定会失败。
详情取决于您使用的语言,但总的来说,这不仅是可能的,而且很有可能。
C 不提供任何保证。你可以说例如
#include <stddef.h>
typedef void (*foo)( void );
int main( void ) {
((foo)NULL)( );
return 0;
}
需要 NULL
,将其转换为一个函数并调用它(或至少尝试,然后崩溃。)在撰写本文时,gcc -Wall
和 clang -Wall
都不会即使是这种病态病例也不会检测或警告。
对于其他语言,可能会有更多的保护措施。但一般来说,不要指望你的程序能在错误的函数指针中幸存下来。
以下示例会产生您提到的分段错误:
int main(int argc, char *argv[]) {
void (*fun_ptr)() = (void (*)()) 1;
(*fun_ptr)();
return 0;
}
None of cc, clang, splint 发出警告。 C 假定程序员知道他在做什么。
更新
以下参考说明了为什么 C 允许通过指针访问绝对内存寻址。
Koenig, Andrew R., C Traps an Pitfalls,贝尔电话实验室,新泽西州默里山,技术备忘录,2.1。理解声明:
I once talked to someone who was writing a C program that was going to run stand-alone in a small microprocessor. When this machine was switched on, the hardware would call the subroutine whose address was stored in location 0.
In order to simulate turning power on, we had to devise a C statement that would call this subroutine explicitly. After some thought, we came up with the following:
(*(void(*)())0)();