如何捕获ctrl-c事件?

165

在C++中如何捕获Ctrl+C事件?


控制台应用程序,Windows 应用程序,还是其他? - GManNickG
9
哪种操作系统?Windows、Linux等。 - shf301
1
这是一个Qt应用程序,但我在开发过程中从控制台运行它。(这是Linux系统) - Scott
4个回答

204

signal 并不是最可靠的方式,因为它在实现中存在差异。我建议使用 sigaction。Tom的代码现在将如下所示:

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

void my_handler(int s){
           printf("Caught signal %d\n",s);
           exit(1); 

}

int main(int argc,char** argv)
{

   struct sigaction sigIntHandler;

   sigIntHandler.sa_handler = my_handler;
   sigemptyset(&sigIntHandler.sa_mask);
   sigIntHandler.sa_flags = 0;

   sigaction(SIGINT, &sigIntHandler, NULL);

   pause();

   return 0;    
}

2
我认为my_handler应该以int s作为它的参数。sig_t本身是一个函数指针类型。 - Matthew Marshall
50
<stdlib.h>等是C语言的头文件,而不是C++。在C++中应该使用<cstdlib>。 - Abyx
11
printf() 不支持异步信号安全,因此不能在信号处理函数中使用。 - P.P
9
这些功能在Windows上不可用。 - Timmmm
3
希望能够对 sa_masksa_flags 进行一些解释。 - qed
显示剩余4条评论

65

对于Windows控制台应用程序,您希望使用SetConsoleCtrlHandler来处理CTRL+CCTRL+BREAK

请参阅这里有一个示例。


50

你需要捕获 SIGINT 信号(我们正在讨论 POSIX 吗?)

请参考 @Gab Royer 的 sigaction 回答。

示例:

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

void my_handler(sig_t s){
           printf("Caught signal %d\n",s);
           exit(1); 

}

int main(int argc,char** argv)
{
   signal (SIGINT,my_handler);

   while(1);
   return 0;

}

1
是的,它是POSIX。我忘了在问题中加入Linux。 - Scott
5
signal()的行为会因为它是遵循BSD还是SysV风格而有所不同。推荐使用sigaction()。 - asveikau
10
我知道这很古老,但是在 g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0 中它无法编译。我不得不将 void my_handler(sig_t s) 更改为 void my_handler(sig_atomic_t s),才能使代码能够编译通过。 - jcmonteiro

2

是的,这是一个与平台相关的问题。

如果您正在POSIX上编写控制台程序,请使用信号API(#include <signal.h>)。

在WIN32 GUI应用程序中,您应该处理WM_KEYDOWN消息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接