C-高阶函数
信号将回调函数作为其参数之一。为了具有可变行为,我想在函数中创建一个函数。这是我迄今为止的尝试:C-高阶函数,c,C,信号将回调函数作为其参数之一。为了具有可变行为,我想在函数中创建一个函数。这是我迄今为止的尝试: typedef void (*sighandler_t)(int); sighandler_t f(int pid) { void sigintHandler(int sig) { printf("Process %d", pid); } return sigintHandler } int main(void) { ... if (sign
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),我都会得到一个seg错误
作为旁注:任何关于如何调试seg故障的提示都非常感谢 我不确定你在问什么,但我可以帮助你理解你的错误 当你调用一个函数时,有几件事要做
无效参数
,因此调用(1)将0
参数推送到堆栈中
而返回(6)将从堆栈中弹出“unexistant”int
,并损坏它
解决方案
您不能有带参数的信号函数,你能做的是:
您的代码可以编译,因为它在语法上是正确的,并且您正在使用编译器扩展;但是,代码中存在一些基本问题,可能会导致出现
segfault
首先,您的信号处理程序代码:
typedef void (*sighandler_t)(int);
sighandler_t f(int pid) {
void sigintHandler(int sig) {
printf("Process %d", pid);
}
return sigintHandler;
}
这是,甚至需要在某些版本的gcc
上指定标志才能实际编译
您的信号处理函数本身有一些问题需要解决:
sigintdhandler
是a,因此当信号处理函数f
通过返回sigintdhandler代码>,您将返回一个函数指针
在您的代码中,这可以正确编译,因为您有typedef void(*sighandler_t)(int)
,它定义了一种函数指针类型,该类型可以指向具有void
返回类型的函数,并将int
作为参数,而sigintHandler
定义为该参数
相反,您的信号处理函数可以简单地写为:
void sigintHandler(int sig) {
printf("Signal %d\n", sig);
}
在主要功能中,您具有以下功能:
if (signal(SIGTSTP, *f(1)) == SIG_ERR) {
// ....
}
if (signal(SIGTSTP, f) == SIG_ERR) {
// ....
}
#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;
}
#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;
}
这里应该指出,这也有一些问题。首先,函数的第一个参数是信号号(通常是标头中定义的宏),第二个参数是指向定义为void func_name(int sig)
的函数的指针
为此,您正在调用函数,而不是将其作为指针传递
*f(1)
实际调用f
传递1
作为其参数;相反,您可以将其更改为以下内容:
if (signal(SIGTSTP, *f(1)) == SIG_ERR) {
// ....
}
if (signal(SIGTSTP, f) == SIG_ERR) {
// ....
}
#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;
}
#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;
}
但这会发出警告/错误,因为f
被定义为返回函数指针,而不是void
因此,要将代码更改为兼容,您只需执行以下操作:
if (signal(SIGTSTP, *f(1)) == SIG_ERR) {
// ....
}
if (signal(SIGTSTP, f) == SIG_ERR) {
// ....
}
#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;
}
#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;
}
任何关于如何调试seg故障的提示都将不胜感激
首先,了解a是什么;然后,您可以使用调试器,如单步执行代码或检查崩溃转储,以查看发生故障的具体位置
希望能有所帮助。标准C不支持在其他函数中定义函数,因此这完全依赖于编译器。为什么需要在另一个函数中定义函数?此外,根据“如果你试图在包含函数退出后通过其地址调用嵌套函数,那么所有的麻烦都会发生。”你不能将pid
放入一个全局变量中(它应该是volatile sig\u atomic\u t
)。是的,我想我可以使用一个全局变量。我是一个相当新手的C程序员,在其他地方,我通常被教导调试任何东西(包括seg故障),使用-g
选项编译程序(假设您使用gcc
),并在调试器下运行。好吧,这不可能工作pid
仅在f()的生存期内存在。在main()
中,您正在将sigintHandler
传递给signal()
。当调用sigintHandler()
时,f()
就再也找不到了,而且pid
的生命周期也结束了。