【问题标题】:Executable suddenly stopped working: silent exit, no errors, no nothing可执行文件突然停止工作:静默退出,没有错误,没有任何东西
【发布时间】:2015-05-22 21:49:37
【问题描述】:

我面临一个相当特殊的问题:我有一个 Qt C++ 应用程序,它曾经可以正常工作。现在,突然我无法再启动它了。没有错误被抛出,什么也没有。

更多信息:

  • 使用 Visual Studio 2012 在调试模式下启动应用程序时的最后一行输出:

程序“[4456] App.exe”已退出,代码为 -1 (0xffffffff)。

  • 实际应用程序代码(= main() 中的第一行)从未被调用或至少没有触发断点,因此无法进行调试。
  • 几秒钟的可执行进程出现在进程列表中,然后又消失了。
  • Win 7 x64 和最新的 Windows 更新。
  • 问题同时出现在两台不同的机器上。
  • 应用程序最初是使用 Qt 5.2.1 构建的。今天我在测试方面切换到 Qt 5.4.1。但不出所料,没有变化。
  • 未对源代码进行任何更改。该问题也适用于应用程序的现有版本。
  • 在我看来,运行 DependencyWalker 并没有产生任何有趣的结果。

我完全没有想法。关于尝试或查看什么的任何指示?一个可执行文件怎么会突然停止工作而没有错误?

【问题讨论】:

  • @KerrekSB 不可能,因为应用程序的代码从未被触发,因此不会调用任何调试器。我已经尝试在 main() 方法的第一行设置断点,但从未达到。应用程序似乎之前退出了。
  • @PhilipAllgaier "... 应用程序的代码永远不会被触发..." The program '[4456] App.exe' has exited with code -1 (0xffffffff). 是什么让你这么认为?错误信息实际上与您的理论背道而驰!
  • @πάνταῥεῖ 我会假设如果代码实际被执行,我在第一行代码中的断点也应该被触发,不是吗?我确实使用了一些单例,但它们每个都是独立的。还考虑到相同的代码以及现有的 EXE 构建曾经可以工作,知道为什么它们的行为可能会突然改变吗?

标签: c++ qt visual-studio-2012 executable exit


【解决方案1】:

我最终找到了这种行为的原因......有点。编码(例如我的单身人士)从来都不是问题(正如我所料,因为代码总是有效的)。相反,一个外部库(SAP RFC SDK)引起了麻烦。

这个库依赖于 ICU Unicode 库和显然特定的版本。因为我不知道这个事实,所以我的应用程序目录中只有我当前使用的 Qt 版本需要的 ICU 库。到目前为止,SAP RFC SDK 的 ICU 库必须已从标准 Windows 路径加载。

最后,某些软件更改(Windows 更新、手动卸载应用程序等)必须删除那些导致所描述的静默失败的库。只需将所需的 ICU 库版本 DLL 复制到我的应用程序文件夹中,即可解决问题。

我唯一不太确定的是,为什么在通过 DependencyWalker 跟踪加载的 DLL 时看不到这一点。

【讨论】:

  • ICU 库在链接时没有链接到 libsapucum.dll,而是在运行时通过 WIN32 API LoadLibrary() 动态加载。 -- 因此 DependencyWalker 没有找到任何东西! -- 如果 LoadLibrary() 没有找到正确版本的 ICU DLL,libsapucum.dll 简单地中止进程。 (不确定,SAP 在这里的想法...)所有这些都发生在可执行文件及其 DLL 的加载期间,在操作系统跳转到您的 main() 之前...
【解决方案2】:

"实际的应用程序代码(= main() 中的第一行)永远不会被调用。因此无法进行调试。"

您可能在调用main() 之前应用了一些静态存储初始化失败。

您的代码中是否使用了任何相互依赖的单例?如果是这样,请将它们合并为一个 singleton(请记住,不应有超过 一个 singleton)。


还要注意,在这种情况下调试仍然是可能的,陷阱是,- 对于我的回答中描述的这种情况-,main() 的身体的第一行被设置为第一个断点默认情况下,当您在调试器中启动程序时。
没有什么能阻止你设置断点,在启动代码实际上到达main() 之前被命中。


至于您从 cmets 的澄清:

“我确实使用 一些 单例......”

如上所述,如果您确实确定需要使用单例,请实际使用单例

否则,您最终可能会为静态存储初始化的未定义顺序而苦苦挣扎。

无论如何,静态存储数据是否相互依赖并不重要,请在整个代码中为它提供一个单一访问点,以避免与各种实例。

与单个实例耦合,可以更轻松地重构代码以使用接口,如果结果证明 singleton 不是一个。

【讨论】:

  • 有什么方法可以调试这些静态初始化(最好使用 Visual Studio)来解决问题的根源吗?我已经在大多数构造函数中设置了断点,以排除这种情况,但到目前为止没有一个被击中。如果这真的是问题,我想知道为什么会突然出现这个问题,因为正如我所说,相同的代码可以完美运行很长时间。
  • @PhilipAllgaier 如前所述,只需在 songletons 构造函数中设置断点,或者在它们初始化的位置设置断点。
  • 我已经尝试过了,但是 - 再次 - 不幸的是没有触发。
  • @PhilipAllgaier IIRC 我描述的技术也适用于 Visual Studio。请更新您的问题以提供MCVE
猜你喜欢
  • 1970-01-01
  • 2019-06-25
  • 1970-01-01
  • 2015-02-21
  • 2013-03-22
  • 1970-01-01
  • 1970-01-01
  • 2020-05-17
  • 2021-10-16
相关资源
最近更新 更多