【问题标题】:Returning QVariantList in Visual Studio 2008 crashes在 Visual Studio 2008 中返回 QVariantList 崩溃
【发布时间】:2011-07-01 12:23:40
【问题描述】:

我们有一个函数可以将从 C 库中检索到的 JSON 对象转换为 QVariants。所有数据类型都可以正常工作——布尔值、数字、字符串、对象/映射——除了列表。当函数返回一个列表时,由于“指定给 RtlValidateHeap 的地址无效”,它在函数退出时崩溃,我认为这意味着发生了双重释放。

以下代码演示了错误:

QVariant no_crash() {
    QVariantMap map;

    map["Hello"] = "world!";
    qDebug() << map;
    return map;
}
// QMap(("Hello", QVariant(QString, "world!") ) )

QVariant crash() {
    QVariantList list;

    list << "Hello world!";
    qDebug() << list;
    return list;
}
// (QVariant(QString, "Hello world!") )

我看过关于这个的帖子,但它们似乎都是关于 Visual Studio 2010 的,它与 Qt SDK 的二进制版本不兼容。我已经使用从http://qt.nokia.com/downloads/sdk-windows-cpp 下载的 Qt 4.7.3 进行了尝试。

当列表超出范围时发生崩溃;只要返回值在调用堆栈中传播回,就不会发生崩溃。


感谢您的回答。

是的,我完全知道当我返回另一个值时编译器会构造一个 QVariant,但我确信编译器隐式构造了一个与我的显式编码相比同样好的 QVarint :-)

从我提供的链接安装时,MinGW 和 Visual Studio 2008 的库都已安装。我已将 \Desktop\Qt\4.7.3\msvc2008\lib 添加到我的全局 lib 文件搜索路径中,当我运行我的程序时,Visual Studio 输出窗口仅列出 \Desktop\Qt\4.7.3\msvc2008 中的 DLL 作为已加载。

错误发生在 msvcr90d.dll 中,大概是在第二次释放内存时。很难说,因为堆栈似乎已被破坏。

该应用程序相当大,只有 GUI 是用 C++ 编写的,其余的都是 C。这可能是个问题吗?程序同时加载 msvcp90d.dll 和 msvcr90d.dll。

【问题讨论】:

  • 我现在正在从源代码构建 Qt。一旦我尝试过,我会在这里添加评论。

标签: visual-studio-2008 qt crash


【解决方案1】:

错误原来是解决方案中的各个项目链接到静态运行时,而 Qt 库链接到动态运行时。

我查看了 20 多个项目的配置,以及那些未包含在解决方案中但链接到的已构建项目的配置,结果发现即使有一个静态链接到 C 运行时,应用程序也会崩溃。

您可以通过打开项目的属性、导航到配置属性->C/C++ 并选择代码生成来更改运行时。运行时库应该是针对发布目标的多线程 DLL 和针对调试目标的多线程调试 DLL。

【讨论】:

    【解决方案2】:

    你的方法签名是

    QVariant crash()
    

    您应该返回一个 QVariant,但您尝试返回一个 QVariantList 而不是 QVariant,它是 QList &lt;QVariant&gt;

    的同义词

    我认为你做不到。

    在我看来,你甚至不应该编译这个。也许这是你的问题?

    【讨论】:

    • QVariants 可以保存 QVariantLists
    【解决方案3】:

    我发现了几个潜在的问题:

    首先,您链接到的 SDK 用于 MinGW 编译器,而不是 Visual Studio。您应该为您的编译器使用正确的 SDK,或者从源代码重新编译 Qt。对于 VS2008,请访问此页面:http://qt.nokia.com/downloads/ 并下载“Qt Libraries for Windows - VS2008”。

    您的代码确实可以编译:发生的情况是它返回了一个包含 QVariantMap 或 QVariantSet 的 QVariant。编译器正在为您构建一个 QVariant。你的代码实际上在做什么:

    QVariant no_crash() {
        QVariantMap map;
    
        map["Hello"] = "world!";
        qDebug() << map;
        return QVariant(map); // This returns a QVariant which contains a map of QVariants
    }
    
    QVariant crash() {
        QVariantList list;
    
        list << "Hello world!";
        qDebug() << list;
        return QVariant(list); // This returns a QVariant which contains a list of QVariants
    }
    

    这应该可以正常工作 - 我只是在这里编译它,它对我有用。您只需要在使用 QVariant 时检查它的类型(例如,在返回的 QVariant 上调用 toString() 将返回一个空字符串,因为它是您调用它的 list,而不是QVariant 列表中)

    【讨论】:

    • 只是为了确保,我下载了仅 Visual Studio 版本。这是一个更快的下载和安装,但它导致了同样的崩溃。
    • 错误原来是解决方案中的各个项目链接到静态运行时,而 Qt 库链接到动态运行时。
    【解决方案4】:

    确保 C/C++ 代码生成中的运行时库选项分别设置为多线程调试 DLL (/MDd) 或多线程 DLL (/MD) 以进行调试和发布。一些Qt类型如QVariantMapQVariantListQModelIndexList可能是用/MD(在Qt的dll中)分配的,当它们被/MT(在应用程序中)释放时,我认为这会导致崩溃。这也可以修复QString::toStdWString() 上的崩溃。为了使这个链接可能忽略所有默认库应该设置为否并且忽略特定库不应该提及 Qt 使用的 crt dll。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-16
      • 1970-01-01
      • 2014-12-30
      • 1970-01-01
      • 2010-09-24
      • 2018-04-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多