¿Cómo puedo atrapar un evento ctrl-c?

133

¿Cómo atrapo un evento Ctrl+ Cen C ++?

Scott
fuente
¿Aplicación de consola, aplicación de Windows o qué?
GManNickG
77
Qué sistema operativo Windows, Linux, etc.
shf301
1
Bueno, es una aplicación Qt, pero la estoy ejecutando desde la consola durante el desarrollo. (Esto es Linux)
Scott

Respuestas:

172

signalno es la forma más confiable, ya que difiere en las implementaciones. Yo recomendaría usar sigaction. El código de Tom ahora se vería así:

#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;    
}
Gab Royer
fuente
1
Creo que my_handler debería tomar int scomo argumento. sig_tes en sí mismo un tipo de puntero de función.
Matthew Marshall
38
<stdlib.h>, etc. - es C, no C ++. En C ++ deberías usar <cstdlib>
Abyx
8
printf()no es seguro para la señal asíncrona, por lo que no se puede usar dentro del controlador de señal.
PP
77
Estas funciones no están disponibles en Windows.
Timmmm
2
Sería bueno tener alguna explicación sobre sa_masky sa_flags.
qed
52

Para una aplicación de consola de Windows, desea usar SetConsoleCtrlHandler para manejar CTRL+ Cy CTRL+ BREAK.

Ver aquí para un ejemplo.

Chris Smith
fuente
40

Tienes que atrapar la señal SIGINT (estamos hablando de POSIX ¿verdad?)

Ver la respuesta de @Gab Royer para seguirction.

Ejemplo:

#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;

}
Tom
fuente
Sí, es POSIX. Olvidé agregar Linux a la pregunta.
Scott
2
signal () se comporta de manera diferente, dependiendo de si sigue el estilo BSD o SysV. sigaction () es preferible.
asveikau
2
Sé que es antiguo, pero esto no se compila en g ++ (Ubuntu 7.4.0-1ubuntu1 ~ 18.04.1) 7.4.0. Tuve que cambiar void my_handler(sig_t s)a void my_handler(sig_atomic_t s).
jcmonteiro
1

Sí, esta es una pregunta dependiente de la plataforma.

Si está escribiendo un programa de consola en POSIX, use la señal API ( #include <signal.h>).

En una aplicación WIN32 GUI debe manejar el WM_KEYDOWNmensaje.

Joyer
fuente