函数指针值的分段错误

时间:2021-02-27 08:52:47

Is it possible to have a Segmentation Fault on if incorrectly set the value of a function pointer?

如果错误地设置了函数指针的值,是否可以启用分段错误?

Or will the interpreter/compiler detect that beforehand?

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

3 个解决方案

#1


The details depend on the language you're using, but in general it's not just possible but likely.

细节取决于您使用的语言,但一般来说,它不仅可能,而且可能。

C provides no guarantees whatsoever. You can just say e.g.

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

#include <stddef.h>

typedef void (*foo)( void );

int main( void ) {
    ((foo)NULL)( );
    return 0;
}

which takes NULL, casts it to a function and calls it (or at least attempts to, and crashes.) As of writing, both gcc -Wall and clang -Wall will neither detect nor warn for even this pathological case.

取值为NULL,将其转换为函数并调用它(或者至少尝试并崩溃。)截至写作时,gcc -Wall和clang -Wall都不会检测也不会警告这个病态。

With other languages, there may be more safeguards in place. But generally, don't expect your program to survive a bad function pointer.

使用其他语言,可能会有更多的保护措施。但一般来说,不要指望你的程序能够在一个糟糕的函数指针中存活。

#2


void  (*ptr)() = (void (*) ())0x0;
ptr();

Nothing prevents you from compiling/executing this, but it will fail for sure.

什么都没有阻止你编译/执行它,但它肯定会失败。

#3


The following example produces the segmentation fault you mention:

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

int main(int argc, char *argv[]) {
    void (*fun_ptr)() = (void (*)()) 1;
    (*fun_ptr)();
    return 0;
}

None of cc, clang, splint issue a warning. C assumes that the programmer knows what he is doing.

cc,clang,splint都没有发出警告。 C假设程序员知道他在做什么。

UPDATE

The following reference illustrates why a C allows for absolute memory addressing to be accessed through pointers.

以下参考说明了为什么C允许通过指针访问绝对存储器寻址。

Koenig, Andrew R., C Traps an Pitfalls, Bell Telephone Laboratories, Murray Hill, New Jersey, Technical Memorandum, 2.1. Understanding Declarations:

Koenig,Andrew R.,C Traps a Pitfalls,Bell Telephone Laboratories,Murray Hill,New Jersey,Technical Memorandum,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.

我曾经和一个正在编写C程序的人交谈,该程序将在一个小型微处理器中独立运行。当该机器打开时,硬件将调用其地址存储在位置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:

为了模拟打开电源,我们必须设计一个C语句,它将明确地调用此子例程。经过一番思考,我们想出了以下内容:

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

#1


The details depend on the language you're using, but in general it's not just possible but likely.

细节取决于您使用的语言,但一般来说,它不仅可能,而且可能。

C provides no guarantees whatsoever. You can just say e.g.

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

#include <stddef.h>

typedef void (*foo)( void );

int main( void ) {
    ((foo)NULL)( );
    return 0;
}

which takes NULL, casts it to a function and calls it (or at least attempts to, and crashes.) As of writing, both gcc -Wall and clang -Wall will neither detect nor warn for even this pathological case.

取值为NULL,将其转换为函数并调用它(或者至少尝试并崩溃。)截至写作时,gcc -Wall和clang -Wall都不会检测也不会警告这个病态。

With other languages, there may be more safeguards in place. But generally, don't expect your program to survive a bad function pointer.

使用其他语言,可能会有更多的保护措施。但一般来说,不要指望你的程序能够在一个糟糕的函数指针中存活。

#2


void  (*ptr)() = (void (*) ())0x0;
ptr();

Nothing prevents you from compiling/executing this, but it will fail for sure.

什么都没有阻止你编译/执行它,但它肯定会失败。

#3


The following example produces the segmentation fault you mention:

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

int main(int argc, char *argv[]) {
    void (*fun_ptr)() = (void (*)()) 1;
    (*fun_ptr)();
    return 0;
}

None of cc, clang, splint issue a warning. C assumes that the programmer knows what he is doing.

cc,clang,splint都没有发出警告。 C假设程序员知道他在做什么。

UPDATE

The following reference illustrates why a C allows for absolute memory addressing to be accessed through pointers.

以下参考说明了为什么C允许通过指针访问绝对存储器寻址。

Koenig, Andrew R., C Traps an Pitfalls, Bell Telephone Laboratories, Murray Hill, New Jersey, Technical Memorandum, 2.1. Understanding Declarations:

Koenig,Andrew R.,C Traps a Pitfalls,Bell Telephone Laboratories,Murray Hill,New Jersey,Technical Memorandum,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.

我曾经和一个正在编写C程序的人交谈,该程序将在一个小型微处理器中独立运行。当该机器打开时,硬件将调用其地址存储在位置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:

为了模拟打开电源,我们必须设计一个C语句,它将明确地调用此子例程。经过一番思考,我们想出了以下内容:

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