35 votes

Le programme avec boucle ne se termine pas avec CTRL + C

J'ai un programme qui doit s'exécuter jusqu'à ce qu'il soit interrompu par l'utilisateur qui appuie sur CTRL + C. Lorsque j'appuie sur CTRL + C, rien ne se passe et je ne peux terminer le programme qu'en le suspendant et en l'arrêtant manuellement ensuite.

C'est la partie du code qui doit s'exécuter à l'infini :

while(true) {
    liveOrDie(field);
    printOut(field);
}

La première fonction calcule s'il faut mettre 1 ou 0 dans un tableau à deux dimensions et la seconde l'imprime en utilisant une boucle for comme ceci :

void printOut(int field[38][102]) {
for(int i = 0; i < 38; i++) {
    for(int j = 0; j < 102; j++) {
        if(field[i][j] == 1) {
            cout << "o";
        }
        else {
            cout << " ";
        }
    }
    cout << endl;
}

system("sleep .1");
}

La mise en veille est utilisée pour qu'il y ait suffisamment de temps pour tout imprimer à l'écran avant qu'il ne soit effacé.

Donc, le programme ne se termine pas par Ctrl+C . Quelle peut être la cause de ce comportement, et comment faire en sorte que le programme se termine après la fin de l'opération ? Ctrl+C ?

85voto

webuster Points 1845

De la documentation de system() (c'est moi qui souligne et met en gras) :

El system() La fonction de bibliothèque utilise fourche(2) pour créer un processus enfant qui exécute la commande shell spécifiée dans command en utilisant execl(3) comme suit :

   execl("/bin/sh", "sh", "-c", command, (char *) 0);

system() revient après la fin de la commande.

Pendant l'exécution de la commande, SIGCHLD sera bloqué, et SIGINT et SIGQUIT seront ignorés, dans le processus qui appelle system() (ces signaux seront traités selon leurs valeurs par défaut à l'intérieur du processus enfant qui exécute commande ).

Ce qui explique votre comportement.

61voto

Paul R Points 104036

Je soupçonne que le code utilisateur s'exécute pendant un petit laps de temps, disons 1 ms, et que le processus de mise en veille provoque le blocage du processus parent pendant 100 ms, donc à moins que vous ne soyez très persévérant avec la fonction CTRL + C alors l'interruption sera très probablement ignorée.

Vous devriez simplement remplacer votre appel à system("sleep .1") avec un appel approprié à la bibliothèque, par exemple change :

system("sleep .1");

à :

usleep(100000);  // NB: requires #include <unistd.h>

Voir : l'homme dort .

2voto

rookie coder Points 135

Avez-vous essayé de capter le signal ? Voir l'exemple de code ci-dessous :

if (signal (SIGINT, yourFunctionHandler) == SIG_ERR)
    {
        cout << "Error setting the SIGINT handler";
    }

void yourFunctionHandler (int signal)
{
    cout << "Signal " << signal << " received!";
    //do what's needed to kill loop
}

De cette façon, vous pouvez modifier la variable de la boucle comme vous le souhaitez. Et comme d'autres personnes l'ont suggéré, n'utilisez pas la fonction système() .

Référence du signal

Petit tutoriel

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X