当前位置: 首页 > 知识库问答 >
问题:

c++ - system("pause")在C++中为何不能阻止程序执行?

韩喜
2024-10-07

关于system("pause"),我知道它可以暂停命令行界面,等待用户的输入。但是对于以下代码,我遇到一些问题:

#include <iostream>
#include <csignal>
#include <Windows.h>

void controlCHandler(int signal)
{
    std::cout << "Control-C detected..." << std::endl;
    //exit(2);
    //return;
    system("pause");
}

int main()
{
    signal(SIGINT, controlCHandler);

    while (true) {
        std::cout << "Sleeping..." << std::endl;
        Sleep(1000);
    }

    return 0;
}

我的运行结果如下:
runResult
其中我按了三次Control-C才结束掉程序。难道pause命令不是把进程阻塞了么?为什么还能继续执行循环呢?这三次Control-C时各自发生了什么事情?

此外,我尝试对程序进行调试,发现在第一个和最后一个Control-C时,VS会报异常:
controlCException
但中间一个并不会。这又是什么原因?

此外,换成return是按两次退出,用exit()直接退出程序是没有问题的,一次退出。

还望各位不吝赐教,感谢!如果需要环境方面的信息随时提出。

共有1个答案

郝哲茂
2024-10-07

问题解答

在C++中,system("pause") 调用确实会在命令行界面中暂停,并等待用户按任意键继续。然而,在你的特定情况下,system("pause") 被放在了一个信号处理函数 controlCHandler 中,这里有几个关键的问题点需要注意:

  1. 信号处理函数的限制

    • 信号处理函数(如 controlCHandler)应当尽可能简单和快速。在信号处理函数中调用像 system() 这样的复杂函数,可能会导致未定义行为,因为信号处理函数在执行时,程序的其他部分可能处于不确定的状态。
    • system() 函数会启动一个新的进程来执行 pause 命令,这涉及到进程创建、执行、等待用户输入等复杂操作,这些操作在信号处理函数中执行可能不安全。
  2. 循环继续执行的原因

    • system("pause") 被调用时,它会暂停当前线程(如果 system() 是在多线程环境下被调用的话,否则就是整个进程),但它不会改变 controlCHandler 函数之后的执行流程。一旦用户按了任意键,pause 命令结束,system() 返回,controlCHandler 函数也随之结束。由于信号处理函数不会自动恢复或改变程序的其他部分(如循环),所以主循环会继续执行。
  3. 异常的原因

    • 当你第一次和最后一次按 Control-C 时,VS 报告异常很可能是因为信号处理函数中的操作(尤其是 system("pause"))与信号处理的上下文发生了冲突。第一次按 Control-C 触发了信号处理,但程序可能尚未准备好处理它(如某些资源尚未释放)。最后一次按 Control-C 时,程序可能已处于不稳定状态,因为已经多次尝试中断循环。
    • 中间的 Control-C 没有触发异常,可能是因为在第一次调用 system("pause") 后,程序状态在某种程度上被重置或稳定了,但这并不意味着这样做是安全的。
  4. 关于 returnexit() 的行为

    • 使用 return 会从 controlCHandler 函数返回,但并不会停止主循环。这是因为 return 只影响当前函数,而不是整个程序。
    • 使用 exit(2); 会立即终止程序,并返回状态码 2 给操作系统。这是处理这类中断的一种更安全、更直接的方式。

建议的解决方案

  • 避免在信号处理函数中使用 system():改用其他方式来处理中断,如设置标志位,然后在主循环中检查这个标志位以决定是否退出循环。
  • 使用 exit():在信号处理函数中直接调用 exit() 来安全地终止程序。

例如,修改你的 controlCHandler 函数如下:

void controlCHandler(int signal)
{
    std::cout << "Control-C detected..." << std::endl;
    exit(2);  // 直接退出程序
}

这样,每次按 Control-C 时,程序都会立即退出,避免了潜在的不确定性和复杂性。

 类似资料:
  • 问题内容: 我应该如何从我的程序中运行另一个程序?我需要能够将数据写入启动的程序中(并可能从中读取) 我不确定这是否是标准的C函数。我需要应该在Linux下工作的解决方案。 问题答案: 您要使用。它为您提供了一个单向管道,您可以使用该管道访问程序的stdin和stdout。 popen是现代unix和类似unix的操作系统的标准配置,其中Linux是其中之一:-) 类型 在终端上阅读有关它的更多信

  • 问题内容: 想知道是否有人知道一种在运行时从C#代码执行Java命令行程序的好方法吗? 它与执行本机.EXE文件相同吗? 它会同步还是异步运行(这意味着我可能必须等待线程完成才能找到结果) 具体来说,我想从服务器端的Web应用程序中调用一个小工具(恰好用Java编写),以对文本文件进行一些处理。我想等待它完成,因为在Java程序完成对文本文件的处理之后,我想获取处理后的文本,并在C#应用程序中使用

  • 问题内容: 我正在阅读有关章节的内容。似乎您可以按以下方式列出节和段之间的映射。 我的问题, 我不明白程序头是什么意思?它们与细分有何关系? 段到段的映射很清楚。但是有人可以命名吗?我只看到数字。我确定了代码段(03),数据段(02)和堆栈(07)。 问题答案: 了解它的输出将帮助您了解文件的格式。请参考本文件。 就了解如何解释此链接的输出而言可能会有帮助。 关于您的问题2,此链接描述了细分。在该

  • 问题内容: 我有一棵divs树: 在div上单击时,将使其子级不可见-即单击“ a”将使“ b”和“ c”不可见。 问题是:单击“ b”将调用“ a”的单击,并使“ b”和“ c”不可见。如何使用jQuery禁用对“ a”的点击? 谢谢 问题答案: 您可以为孩子添加一个处理程序,以防止click事件蔓延: 这样一来,点击不会传播到。都不会单击以转到,因此也不会。

  • 本文向大家介绍C#实现终止正在执行的线程,包括了C#实现终止正在执行的线程的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#实现终止正在执行的线程的实现方法,并针对一些容易出错的地方进行了深入分析,具体方法如下: 一般来说,很多人都会使用Abort方法来终止线程,其实这种做法并不可取!如果你的线程正在操作临界资源,很有可能会造成资源没有正确释放而出现死锁问题。正确的做法应该是使用标记来终

  • 问题内容: 看完管道和Jenkinsfile文档后,我对如何创建 _舞台- >生产_管道感到困惑。 一种方法是使用类似 这似乎有点笨拙,因为这将一直阻塞执行程序,直到您要部署到生产环境为止。Jenkins是否有其他任何可以部署到生产环境的方法。 问题答案: 编辑(2016年10月):请参阅下面的其他答案“使用里程碑并锁定”,其中包括最近引入的功能。 作为第一个选择,您可以将您的步骤包装为一个步骤。