Pointers 函数指针值的分段错误

Pointers 函数指针值的分段错误,pointers,segmentation-fault,Pointers,Segmentation Fault,如果函数指针的值设置不正确,是否可能出现分段故障 或者解释器/编译器会事先检测到吗 void (*ptr)() = (void (*) ())0x0; ptr(); 没有任何东西阻止您编译/执行此操作,但它肯定会失败 没有任何东西阻止您编译/执行此操作,但它肯定会失败。详细信息取决于您使用的语言,但一般来说,这不仅是可能的,而且很可能 C不提供任何保证。你可以说 #include <stddef.h> typedef void (*foo)( void ); int main

如果函数指针的值设置不正确,是否可能出现
分段故障

或者解释器/编译器会事先检测到吗

void  (*ptr)() = (void (*) ())0x0;
ptr();
没有任何东西阻止您编译/执行此操作,但它肯定会失败


没有任何东西阻止您编译/执行此操作,但它肯定会失败。

详细信息取决于您使用的语言,但一般来说,这不仅是可能的,而且很可能

C不提供任何保证。你可以说

#include <stddef.h>

typedef void (*foo)( void );

int main( void ) {
    ((foo)NULL)( );
    return 0;
}
#包括
类型定义无效(*foo)(无效);
内部主(空){
((foo)NULL)();
返回0;
}
它接受
NULL
,将其强制转换为一个函数并调用它(或者至少尝试调用,然后崩溃。)在编写本文时,
gcc-Wall
clang-Wall
都不会检测到这种病理情况,也不会发出警告


对于其他语言,可能有更多的保护措施。但是,一般来说,不要期望你的程序在一个糟糕的函数指针下生存。

细节取决于你使用的语言,但一般来说,这不仅是可能的,而且是可能的

C不提供任何保证。你可以说

#include <stddef.h>

typedef void (*foo)( void );

int main( void ) {
    ((foo)NULL)( );
    return 0;
}
#包括
类型定义无效(*foo)(无效);
内部主(空){
((foo)NULL)();
返回0;
}
它接受
NULL
,将其强制转换为一个函数并调用它(或者至少尝试调用,然后崩溃。)在编写本文时,
gcc-Wall
clang-Wall
都不会检测到这种病理情况,也不会发出警告


对于其他语言,可能有更多的保护措施。但是,一般来说,不要期望程序在错误的函数指针下生存。

下面的示例会产生您提到的分段错误:

int main(int argc, char *argv[]) {
    void (*fun_ptr)() = (void (*)()) 1;
    (*fun_ptr)();
    return 0;
}
cc、叮当声、夹板声均未发出警告。C假设程序员知道他在做什么

更新

下面的参考说明了为什么C允许通过指针访问绝对内存寻址

Andrew R.Koenig,贝尔电话实验室,新泽西州默里山,技术备忘录,2.1。谅解声明:

我曾经和一个正在编写C程序的人交谈过,这个程序将 在小型微处理器中独立运行。当这台机器 打开时,硬件将调用地址为的子例程 存储在位置0中

为了模拟打开电源,我们必须设计一个C语句 这将显式调用此子例程。经过一番思考,我们 得出以下结论:

(*(void(*)()0)()


以下示例生成您提到的分段错误:

int main(int argc, char *argv[]) {
    void (*fun_ptr)() = (void (*)()) 1;
    (*fun_ptr)();
    return 0;
}
cc、叮当声、夹板声均未发出警告。C假设程序员知道他在做什么

更新

下面的参考说明了为什么C允许通过指针访问绝对内存寻址

Andrew R.Koenig,贝尔电话实验室,新泽西州默里山,技术备忘录,2.1。谅解声明:

我曾经和一个正在编写C程序的人交谈过,这个程序将 在小型微处理器中独立运行。当这台机器 打开时,硬件将调用地址为的子例程 存储在位置0中

为了模拟打开电源,我们必须设计一个C语句 这将显式调用此子例程。经过一番思考,我们 得出以下结论:

(*(void(*)()0)()


编译器将预先检测它。函数指针只能设置为与指针预期的原型声明相同的函数名。例如,您声明了
size\u t(*funcptr)(intfd,void*buf,size\u t count)
funcptr
可以设置为
read
,但不能设置为
strcpy
。编译器将检测它。编译器将事先检测它。函数指针只能设置为与指针预期的原型声明相同的函数名。例如,您声明了
size\u t(*funcptr)(intfd,void*buf,size\u t count)
funcptr
可以设置为
read
,但不能设置为
strcpy
。编译器将检测它。例如+1。这是经过深思熟虑的,绝对有可能。我猜OP更多地考虑了非故意的程序错误。例如+1。这是经过深思熟虑的,绝对有可能。我猜OP考虑的更多的是非故意的程序错误。这是故意的。我猜OP要求的是非故意的程序错误。那是故意的。我猜OP要求的是非故意的程序错误。