信号处理错误



当我使用my_handler作为函数时,没有错误,但我不能,因为我必须在那里使用另一种方法。

如果我在下面构建代码:错误:成员函数的使用无效 上(你忘记了"()"吗?

这是我在C++的第一个程序

void Client::my_handler(int s){
if (s == SIGINT){
printf("SIGINTn");
// here I have to use stop_thread method 
}
}

int main (int argc, const char **argv) {
Client client(argc, argv);
client.before_start();
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = (__sighandler_t) client.my_handler; //error here
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
client.run();
return 0;
}

在C++中,成员函数(与类实例关联的函数,例如此处的client.my_handler)与常规函数(类似于此处的int main(int arg, const char** argv))不同。这就是为什么你不能把client.my_handler投到__sighandler_t.

Client::my_handler有一个隐藏的参数,一个Client*。所以真的,它的签名(从某个角度来看)看起来像void my_handler(Client* this, int s).C++幕后做一些事情,这样您就可以引用this的变量,而无需执行this->(大多数情况下)。当你做一些像打电话这样的事情时

client.my_handler(SIGINT)

C++正在将其转换为

my_handler(&client, SIGINT)

也许现在你可以看到问题了:__sighandler_t是函数指针的别名,但client.my_handler实际上是两个指针:my_handler的函数指针和client的指针。

信号处理程序只接受函数指针,不接受更通用的函数对象(函数指针加上一些其他数据)。信号处理来自 C,但函数对象来自 C++。

信号处理程序的唯一解决方案是某种全局变量。

@SJL很好地解释了为什么这不起作用,并提供了一个C风格的解决方法。

如果可以使用 Boost,则boost::asio::signal_set可用于以更C++的风格处理信号。async_wait函数可以接收 lambda、绑定成员函数指针或任何其他具有相应签名的可调用类型。

最新更新