C - 高阶函数

标签 c

Signal 将回调函数作为其参数之一。要具有可变行为,我想在函数内创建一个函数。到目前为止,这是我的尝试:

typedef void (*sighandler_t)(int);
sighandler_t f(int pid) {
    void sigintHandler(int sig) {
        printf("Process %d", pid);
    }
    return sigintHandler
}

int main(void) {
    ...
    if (signal(SIGTSTP, *f(1)) == SIG_ERR) {
        ...
    }
    ...
}

但是,每次我发送 SIGTSTP (Ctrl-z) 时,我都会遇到段错误。


作为旁注:任何关于如何调试一般段错误的提示都将不胜感激!

最佳答案

您的代码可以编译,因为它在语法上是正确的,并且您正在使用编译器扩展;但是,您的代码存在一些基本问题,可能会导致您的段错误

首先,您的信号处理程序代码:

typedef void (*sighandler_t)(int);
sighandler_t f(int pid) {
    void sigintHandler(int sig) {
        printf("Process %d", pid);
    }
    return sigintHandler;
}

这是 not standard C甚至需要 -ftrampolines在某些版本的 gcc 上指定标志以实际编译。

您的信号处理函数本身有一些问题需要解决:

sigintHandler 是一个 nested function ,因此当您的信号处理函数 f 通过 return sigintHandler; 返回时,您将返回一个函数指针。

在您的代码中,这可以正确编译,因为您有 typedef void (*sighandler_t)(int);,它定义了一个函数指针类型,可以指向具有 void< 的函数 返回类型并将 int 作为参数,您的 sigintHandler 被定义为。

相反,您的信号处理函数可以简单地写成:

void sigintHandler(int sig) {
    printf("Signal %d\n", sig);
}

在你的主要功能中,你有以下内容:

if (signal(SIGTSTP, *f(1)) == SIG_ERR) {
    // ....    
}

这里需要注意的是,这也存在一些问题。首先,signal函数的第一个参数是信号编号(通常是在 signal.h header 中定义的宏),第二个参数是指向定义为 void func_name(int sig) 的函数的指针。

为此,您调用函数而不是将其作为指针传递。

*f(1) 实际上调用了 f 并将 1 作为其参数;相反,您可以将其更改为以下内容:

if (signal(SIGTSTP, f) == SIG_ERR) {
    // ....    
}

但这应该发出警告/错误,因为 f 被定义为返回函数指针而不是 void

因此,要更改代码以使其合规,您只需执行以下操作:

#include <stdio.h>
#include <signal.h>

void sigintHandler(int sig) {
    printf("Signal %d", sig);
}

int main(void) {
    // ...
    if (signal(SIGTSTP, sigintHandler) == SIG_ERR) {
        // ...
    }
    // ...
    return 0;
}

但是你说:

To have variable behaviour ...

这取决于您想要的变量性质,但如果它是基于信号的变量函数,您可以执行以下操作:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void sig_stop(int sig) {
    printf("Process %d stop\n", getpid());
}

void sig_int(int sig) {
    printf("Process %d interrupt\n", getpid());
}

int main(void) {
    // ...
    if (signal(SIGTSTP, sig_stop) == SIG_ERR) {
        // ...
    }
    if (signal(SIGINT, sig_int) == SIG_ERR) {
        // ...
    }
    // ...
    return 0;
}

或者您可以使用 switch 语句:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void sigHandler(int sig) {
    printf("Process %d received %d\n", getpid(), sig);
    switch (sig) {
        case SIGTSTP:
            // do stop code
            break;
        case SIGINT:
            // do interupt code
            break;
    }
}

int main(void) {
    // ...
    if (signal(SIGTSTP, sigHandler) == SIG_ERR) {
        // ...
    }
    if (signal(SIGINT, sigHandler) == SIG_ERR) {
        // ...
    }
    // ...
    return 0;
}

any tips on how to debug seg faults in general would be really appreciated!

首先,了解什么是segmentation fault是;然后你可以使用像gdb这样的调试器单步执行您的代码或检查故障转储以查看发生段错误的具体位置。

希望对您有所帮助。

关于C - 高阶函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41771552/

相关文章:

c++ - 使用 gcc 和 g++ 分别编译包含 C 和 C++ 文件的项目?

Cairo C 程序不会绘制到 x11 窗口

c - 在 RTP 数据包中使用 FFmpeg 解码 AAC

objective-c - 混合 C 和 objective-C

c - 字符串反转 C 中的逻辑错误

c - 系统调用和 EINTR 错误代码

C 风格编码和动态数组

C 宏定义中的逗号 (,)

c - 如何创建动态大小的结构数组?

c - p 是一个指向结构的指针,所有这些代码片段都做了什么?