【问题标题】:Instant crash on throw statement with Qt5使用 Qt5 的 throw 语句即时崩溃
【发布时间】:2013-11-17 11:03:56
【问题描述】:

当我尝试在 Qt 中使用异常时,应用程序在任何 throw 语句上都会立即崩溃,而忽略任何 catch(...)-clauses。这是导致崩溃的最少代码:

#include <QString>

int main ( ) {
    try {
        throw 1;
    } catch (...) {
        QString a;
    }
}

没有QString,即使包含库,它也可以正常工作。

我得到的异常代码是

40000015

和偏移量:

0000bb3f

我将 QtCreator 2.7.2Qt 5.1.0mingw 4.8(QtCreator 附带的版本)一起使用。 我使用 Windows 8 进行构建。

在网络上进行了一些研究后,我尝试将 CONFIG+=exceptions 标志添加到 *.pro 文件中,但仍然出现崩溃。 当我读到 Qt 可以毫无例外地构建时(无论这意味着什么),我检查了默认值,因为我使用的是 QtCreator 附带的预编译版本;这个应该包含异常。

我在预编译器之后检查了临时代码,并且预编译器没有对 main 函数进行任何更改。

当我尝试调试代码时,我注意到它在 throw 语句之后没有执行任何行,它确实崩溃了。

我还是 Qt 的初学者;这是 Qt 构建的问题吗?我应该买一个更新的吗?还是我错过了一些我可以更改以使其正常工作的配置?

编辑:在 Frank Osterfeld 要求我之后,我尝试了其他几个课程。以下是我的发现:

  • 按预期工作:
    • std::string
    • QPoint
    • QChar
    • QDate
    • QMessageLogger
  • 崩溃:
    • QString
    • QByteArray
    • QDir
    • QException
    • QFile
    • QRegularExpression
    • QSet&lt;int&gt;
    • QTimer

【问题讨论】:

  • 适用于 gcc 4.7.2 (Linux),同时适用于 Qt 4.8.5 和 Qt 5.1.1。无需在 .pro 文件中配置任何有关异常的内容。我也无法想象这是一个通用的 Qt 问题。也许是特定于mingw的东西。检查它是否也发生在 QString 以外的其他类(比如 QByteArray 或只是一个 QPoint)
  • 知道它是否适用于 std::string 也会很有趣。
  • std::string 效果很好。 QByteArray 也会崩溃;但 QPoint 按预期工作
  • 也尝试了其他一些课程;与他们更新的问题
  • 您的系统中没有其他版本的 Qt 或 MinGW,是吗?如果是这样,请卸载它们。 MinGW 有 3 种不同的“风格”,具有不同的异常处理机制:DWARF-2、SEH、SJLJ。如果您有多个版本的库或编译器,则可能会发生不兼容版本之间的交叉链接,从而导致奇怪的崩溃。

标签: c++ exception-handling mingw qt5


【解决方案1】:

Qt 应用程序在任何 throw 语句上都会立即崩溃 - 我发现在使用标志 -static 编译应用程序时会发生这种情况。

QMAKE_LFLAGS *= -static

环境:Qt 5.5.1,mingw 32bit 运行时,Windows 8。

【讨论】:

  • 有趣的发现。我不确定这是否会解决我的问题,因为它在重新安装机器后可以工作;但我不确定重新安装后我安装的 Qt 是否有所不同。不幸的是,我不能再尝试了。用问题中的我的代码知道问题是否出现在您的机器上会很有趣,并试验它是否适用于即QPoint,而它是否因QString 而失败。为发现 +1。
【解决方案2】:

我终于通过重新安装整个计算机解决了这个问题。 无论如何我都必须这样做,当我下载新版本的 QtCreator (3.0.0) 时,它解决了问题。

也许重新安装 Qt 就足够了。

【讨论】:

  • 我不确定这是否真的是“解决方案”......不过,整个事情确实很奇怪,我遇到了一个非常相似的问题,我也无法弄清楚(见我的回答)。
  • 嗯,这不是一个简单的解决方案,但它解决了我的问题。因此,我会将其视为一种解决方案。
【解决方案3】:

我使用的是 Qt 5.2.1。

我遇到过这种抛出会导致应用程序崩溃的情况(但并非总是如此!):

try{ throw; } catch(...){ }

我把它换成了

try{ throw 1; } catch(...){ }

它解决了这个问题。不确定为什么或何时需要进行此更改,但这可能会对某人有所帮助...

【讨论】:

  • 没有连续对象(或“事物”)要抛出的 throw 语句是 only allowed within a catch-block 并重新抛出捕获的异常。所以你可以使用try { /* some code */ } catch (...) { throw; },但永远不要在捕获之外使用throw;
  • 确切地说是允许在外面,但在这种情况下会立即致电std::terminate
  • 谢谢。那讲得通。唯一的问题是我很确定这在某些情况下是有效的……我必须检查代码。如果在 try{} 中调用了一个引发异常的函数,它会起作用吗?或者,如果这是在另一个包含 try/catch 的函数中发现的?
  • 只有在throw; 以某种方式位于catch 块内时才会起作用。我想如果throw; 位于从捕获块调用的函数中,它可能 工作,但我还没有尝试过。但我可以很好地想象这可能会导致非常奇怪的行为。
  • 另一个想法:如果有人为std::terminate 安装了非默认处理程序,代码可能不会导致崩溃。不过,我会认为这是非常糟糕的做法,并且无法想象这是一个好主意的情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-18
  • 1970-01-01
  • 1970-01-01
  • 2013-03-26
  • 1970-01-01
  • 2018-06-13
  • 1970-01-01
相关资源
最近更新 更多