【问题标题】:How to debug program crashing before main()如何在 main() 之前调试程序崩溃
【发布时间】:2019-09-25 19:27:58
【问题描述】:

我在 Windows 8.1 上使用 QtCreator 和 Visual Studio 2015 工具包来构建我在 Linux 上开发和测试的程序,在 Linux 上它可以正常工作,但在 Windows 上它只是立即崩溃,我不知道该看什么为。

除了我使用的 QT 之外,唯一的外部库是 opengl 和 glew,所以我认为不是这些。

有什么已知的东西可以在 GNU C++ 中工作,但在 MSVC 中会立即崩溃?

【问题讨论】:

  • 像往常一样,尝试将某些事情减少到最小的可重现情况。可以影响此类事情的一件事是全局变量、它们的构造函数以及总大小。根据具体情况,对象可能会从数据部分移动到堆栈中。并且堆栈大小可能会受到限制。但是,再次尝试尽可能多地删除准系统案例并确定您是否仍然会崩溃。或者,嘿,在调试器中启动它,看看你得到了什么样的堆栈跟踪。
  • 它崩溃了——好的。但是当你在 MSVC 调试器下运行它时,错误信息是什么?断言错误?访问违规?缺少文件(dll 等)?什么?
  • @quetzacoatl sigsevs,我不知道如何将 MSVC 调试器链接到 Qt Creator,如果我不从 QtCreator 中打开它,它就找不到 qt5widgets.dll。我可以从 minGW 将 QtCreator 链接到 GDB,但我不确定这些符号在这种情况下是否有效。
  • 如果您使用的是预构建的二进制文件,请确保您使用的是与您的编译器匹配的二进制文件。为 Mingw 构建的二进制文件不适用于 MSVC,反之亦然。

标签: c++ windows qt


【解决方案1】:

通常这种崩溃与您的程序完全无关。这是一个外部库链接问题。我最近在使用 OpenSplice DDS 库时遇到了这个问题。我链接到一个在任何事情开始之前导致分段错误的库。我通过一一链接预编译的库解决了这个问题,并检查每个是否修复了程序。

我建议您做的是:逐渐删除您要链接的库和资源,直到您的程序启动并从main() 的第一行打印“Hello world”。

另一种方法是,创建一个新的空程序,并链接您在程序中使用的相同资源。这更容易,因为它不涉及修改您的程序。

【讨论】:

  • "main() 之前的调试,不存在!"当然可以。对于我至少使用的调试器,您可以将断点添加到将在进入 main 之前调用的代码中,并且调试器将在这些断点处中断。
  • @Quant 构造像 cout 和 cin 这样的对象。但是还有很多很多其他的例子。
  • 我将其他全局构造函数使用的全局变量包装在 std::list & timer_list() { static std::list list;返回列表; } 希望能控制施工顺序,这真的可行吗?
  • @PatrickJeeves 如果您的代码已经在 Linux 中运行,那么您不太可能出现编码错误。还可以考虑在 linux 中使用关键字-pedantic 使其偏执。除了链接问题之外,我看到的唯一可能性是您正在做一些依赖于编译器的事情。您可以使用 -pedantic 摆脱它。
  • 看看 cmets,Neil Butterworth 说这不是真的,但我之前没见过
【解决方案2】:

这就是我会做的。

首先从干净的状态重新构建整个解决方案或项目。以防万一这只是一些奇怪的依赖问题,导致某些东西没有被重新编译。永远不会痛。

正如尼尔在问题的 cmets 中所说,崩溃可能来自全局变量,该变量的构造函数在 main 或 WinMain 之前运行。你确定你没有声明为“静态”或在全局范围内可能有构造函数的东西吗?

现在执行以下操作:

  • 打开 Visual Studio。

  • 从菜单中选择文件->打开->项目/解决方案...

  • 当文件打开对话框弹出时,选择Qt生成的EXE 创造者。 (没错 - 您正在将 EXE 作为项目打开)。此目录通常位于 Qt 项目之上一层文件夹 (..\build-yourapp-Desktop_Qt_5_7_0_MSVC2015_32bit-Debug\debug)

  • 现在按绿色箭头开始调试(菜单->调试->开始 调试)。如果一切顺利,您的程序将提前失败并

现在程序根本无法在 Visual Studio 下运行的可能性很高,因为 Qt Creator 不会将所有 Qt*.dll 二进制文件复制到您的构建目录。您会弹出一堆对话框,说“程序无法启动,因为找不到 Qt5-XYZ.dll”。通过以下任何一种方式更新您的 PATH 环境以将您的 Qt5.x.0\5.x\msvc2015\bin 文件夹包含到您的 PATH 中,可以轻松解决此问题。

  • 从命令 linke 添加它,然后从命令行重新启动 devenv.exe。

  • 您可以从“控制面板”->“系统”->“高级”全局添加它。然后从 Windows 桌面重新启动 Visual Studio。

  • 从 Visual Studio 中打开 EXE 调试项目后,只需右键单击项目名称(不是父解决方案),就会弹出一个对话框,允许您编辑启动设置。其中之一是环境。

应该这样做。从那里您可以在您的 EXE 上启动调试器,根据需要设置断点,并在崩溃时分析调用堆栈。

【讨论】:

  • 谢谢,将静态单例实例初始化为 nullptr 而不是新对象解决了我的问题。
【解决方案3】:

这真的很简单:使用调试信息构建您使用的所有库,包括 Qt(只要生成 PDB 文件,这些库就可以是发布版本)。然后在调试器下运行您的应用程序(例如 Qt Creator 下的 F5),它将在崩溃点停止。

main 之前运行并且已知会导致问题的代码将是全局对象初始化:您可能会遇到static initialization order fiasco

【讨论】:

    【解决方案4】:

    问题的另一个原因可能是堆栈溢出。在 Linux 中,默认堆栈大小通常为 8 MB,而在 Windows 中仅为 1 MB。

    尝试与 /STACK:8388608 开关链接。如果可行,您可以考虑在堆上分配更多数据并保持默认堆栈大小 1 MB。

    【讨论】:

      猜你喜欢
      • 2013-08-08
      • 1970-01-01
      • 2012-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多