【问题标题】:Is it possible to kill a C++ application on Windows XP without unwinding the call stack?是否可以在不展开调用堆栈的情况下杀死 Windows XP 上的 C++ 应用程序?
【发布时间】:2010-11-22 20:22:53
【问题描述】:

我的理解是,当您在 Windows XP 中通过任务管理器杀死 C++ 应用程序时,该应用程序仍然“干净”地被破坏 - 即调用堆栈将展开并且所有相关的对象析构函数都将被调用。不知道我的理解是否有误。

是否可以在不展开堆栈的情况下立即终止此类应用程序?

例如,应用程序可能会使用 RAII 模式,当对象被破坏时会破坏或释放资源。如果通过任务管理器的传统“终止进程”是正常的,那么提供一种立即终止应用程序的方法可以让我测试不正常的关机(例如断电)。

编辑:

澄清一下,我正在寻找一个可以让我这样做的现有实用程序或程序。我应该能够在我没有源代码的程序上使用该解决方案,这意味着程序化解决方案实际上是不可接受的。

编辑:

只是为了提供更多上下文,有时我必须使用非常侵入性的 3rd 方服务(例如,每隔一小时就唠叨我重新启动)。因为我知道我不需要需要重新启动,所以我想终止进程/服务,这样它就不会再烦我了。不幸的是,一些 3rd 方开发人员“聪明”到足以阻止我这样做,当我通过任务管理器终止进程时,系统将立即重启(我猜是使用 RAII 来实现这一点)。

【问题讨论】:

  • 我怀疑 nag 服务的重生使用的是 RAII。
  • nag 服务没有重新生成 - 它正在被杀死,但在死亡时计算机将重新启动。
  • 对我来说,这听起来好像 nag 进程是由另一个进程产生的,它实际上只是在等待 nag 进程完成以便它可以重新启动。您是否尝试过使用 Process Explorer 查看是否有另一个 3rd 方进程被列为 nag 进程的父进程?如果是这样,也许你可以杀死父进程(或者至少在杀死 nag 进程之前暂停它)。
  • 不属于 SO,我引用:“程序化解决方案并不是我真正追求的”
  • 任务管理器的“进程”选项卡强制终止。 “应用程序”选项卡执行您所说的干净关闭。

标签: c++ process windows-xp callstack raii


【解决方案1】:

我相信任务管理器会通过发送 WM_CLOSE 消息尝试“很好地”关闭,然后如果应用程序没有响应,它就会被杀死。

此调用应立即终止进程而不会发出警告:

TerminateProcess

例如:

TerminateProcess(GetCurrentProcess(), 1);

更新:

您可能会觉得这篇文章很有趣:

Quitting time: exiting a C++ program

更新 2:

我应该能够在我没有源代码的程序上使用该解决方案

嗯,这在 99.9% 的情况下都是不受欢迎的行为。

SysInternals 有一个名为 pskill 的实用程序:

http://technet.microsoft.com/en-us/sysinternals/bb896683.aspx

但我不确定它有多“好”。

你可能需要自己动手,但这应该很容易:

DWORD pid = <get pid from command line>;

TerminateProcess(OpenProcess(PROCESS_TERMINATE, FALSE, pid));

【讨论】:

  • 我编辑了这个问题 - 我正在寻找一个可以杀死 另一个 进程的实用程序/程序。程序化解决方案并不是我真正想要的。
  • 如果您愿意,可以将不同的进程句柄传递给 TerminateProcess。
  • 此外,任务管理器可以通过查看并选择其中的列来显示每个进程的 ID(需要提供给 OpenProcess 的 PID)。
【解决方案2】:

不依赖第三方工具的标准 Windows 方法是使用taskkill /f:

taskkill /f <process-id>
taskkill /f /im <process-executable-name> 

/f在这里表示“强制”,确保进程无条件立即终止,没有查询或警告。

【讨论】:

    【解决方案3】:

    除非我大错特错(我只是做了一些测试来确认),否则任务管理器会尝试根据您使用的选项卡以不同的方式关闭程序。如果通过 Applications 选项卡并按下 End Task,它将尝试通过首先发送 WM_CLOSE 干净地关闭程序。但是如果通过 Processes 选项卡并按下 End Process,它似乎使用了 TerminateProcess 的一些东西,这意味着没有堆栈展开等。

    首先,如果您没有在“进程”选项卡上使用“结束进程”,请尝试一下。

    如果这是您已经尝试过的,并且他们的软件仍然设法以某种方式重新启动系统,那么事情就会变得更加复杂。其他人可能对存在其他流程的看法是正确的。

    【讨论】:

    • 谢谢 - 我在“进程”选项卡上使用“结束进程”。
    【解决方案4】:

    我相信 C 标准库方法 exit(0); 会做到这一点,在不调用任何析构函数、释放器等的情况下中止程序。

    试试看,如果它满足您的需求,请告诉我?

    【讨论】:

    • 我编辑了这个问题 - 我正在寻找一个可以杀死另一个进程的实用程序/程序。程序化解决方案并不是我真正想要的。
    • exit() 将为静态存储对象调用析构函数。您想调用 abort() 以避免调用析构函数。
    • _exit() 是“没有清理的死”C 函数,而不是 exit()。鉴于实际问题,正确答案是 TerminateProcess()。
    【解决方案5】:

    看起来 abort() 会给你一个异常退出。

    ANSI 4.10.4.1 abort 函数对打开和临时文件的行为 abort 函数不会关闭打开的或临时的文件。它不刷新流 缓冲区 [source]

    和

    中止当前进程 以异常的程序终止中止进程。 该函数生成 SIGABRT 信号,默认情况下会导致程序终止 > 将不成功的终止错误代码返回给主机环境。 程序在不执行自动或静态对象的析构函数的情况下终止 存储持续时间,并且不调用任何 atexit 函数。 该函数永远不会返回给它的调用者。 [source]

    【讨论】:

    • 我编辑了这个问题 - 我正在寻找一个可以杀死另一个进程的实用程序/程序。程序化解决方案并不是我真正想要的。
    【解决方案6】:

    我会按照Tim above 的建议尝试PSKill。我猜这也会失败。如果 3rd 方服务真的很想避免死亡,那么服务定义可能会设置为“rebo​​ot on crash”。另一种常见的方法是让另一个服务看门狗作为主要服务。主要服务通常设置一个全局事件或使用看门狗服务监视的其他通知机制。如果主服务没有通知看门狗,那么看门狗会重新启动计算机。

    【讨论】:

      【解决方案7】:

      恰如其分地命名为 Kill Tool,可从 Microsoft 下载获得。也是 Windbg 套件的一部分。

      Kill 工具 kill.exe 终止 一个或多个进程及其所有 线程。此工具仅适用于 在本地运行的进程 电脑。

      kill /f <process>
      

      例如,kill /f lsass(开个玩笑,不要不要杀死 LSA!)。 如果您想自己动手,TerminateProcess 是您的不二之选。

      【讨论】:

        【解决方案8】:

        标准库中的 C 函数 abort() 将立即终止您的应用程序而无需清理。

        C++ 定义了一个标准的全局函数 terminate()。调用它也会立即退出您的应用程序。

        从技术上讲,terminate() 的行为可以被 set_terminate 函数覆盖。它默认调用 abort。

        【讨论】:

          【解决方案9】:

          周围有一些实用程序可以禁止重新启动。

          HideToolz 就是这样做的——例如,在某处埋有一个复选框,它会在某事启动重新启动时询问您。它被许多防病毒软件检测为 rootkit(确实如此,但这个被认为是驯服的),因此在您没有完全控制权的系统上运行可能是探测性的(当域策略要求防病毒软件等时)

          【讨论】:

            猜你喜欢
            • 2013-08-05
            • 1970-01-01
            • 2022-12-20
            • 1970-01-01
            • 2018-08-20
            • 2015-06-06
            • 2012-01-17
            • 2013-11-18
            • 2012-02-19
            相关资源
            最近更新 更多