【问题标题】:Program with loop will not terminate with CTRL + C带有循环的程序不会用 CTRL + C 终止
【发布时间】:2014-10-19 13:26:45
【问题描述】:

我有一个程序要运行,直到被用户按 CTRL + C 中断。当我按下它时,什么也没有发生,我只能通过暂停程序并在此之后手动终止它来终止程序。

这是需要无限运行的代码部分:

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

第一个函数计算是否将 1 或 0 放入二维数组,第二个函数使用 for 循环将其打印出来,如下所示:

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");
}

使用睡眠,以便在清除之前有足够的时间在屏幕上打印所有内容。

因此,程序不会以Ctrl+C 终止。什么可能导致这种行为,以及如何使程序在Ctrl+C 之后终止?

【问题讨论】:

  • 尝试使用 CTRL+Z 杀死
  • 您可能正在杀死 systemsleep 的调用而不是您自己的代码 - 使用适当的库调用进行睡眠而不是炮击,例如sleep(1).
  • 这是人生游戏吗?
  • 是的,这是生命游戏。

标签: c infinite


【解决方案1】:

来自system()documentation(强调/粗体):

system() 库函数使用fork(2) 创建子进程 使用execl(3)执行命令中指定的shell命令 如下:

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

system() 在命令完成后返回。

在命令执行过程中,SIGCHLD会被阻塞,SIGINT和SIGQUIT会被忽略,在调用system()的进程中(这些信号会在子进程内部按照它们的默认值进行处理)执行命令的进程)。

这解释了你的行为。

【讨论】:

  • +1 用于提供实际文档。另外,请不要使用 die.net,它已经过时了。
  • 更新了文档。
【解决方案2】:

我怀疑用户代码运行了一小段时间,比如 1 毫秒,而睡眠进程导致父进程阻塞 100 毫秒,所以除非你非常坚持使用 CTRL + C 键,那么中断很可能会被忽略。

您应该将您对 system("sleep .1") 的调用替换为适当的库调用,例如改变:

system("sleep .1");

到:

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

请参阅:man usleep

【讨论】:

  • 我认为命令 usleep(1000) 也适用于人类 v2.0 以后
【解决方案3】:

您是否尝试过捕捉信号?请看下面的示例代码:

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
}

通过这种方式,您可以根据需要修改循环变量。正如其他人建议的那样,不要使用 system()

Signal reference

Small tutorial

【讨论】:

  • 问题是,system 很可能会覆盖您的信号处理程序(无论是默认的还是您自己的)。
  • 这就是为什么我添加了 don't use system() :-)
猜你喜欢
  • 2014-07-10
  • 1970-01-01
  • 1970-01-01
  • 2011-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-11
  • 2018-11-04
相关资源
最近更新 更多