QString::toStdString()在std::string析构函数上崩溃

15

我已经调试了2个小时了,最终问题出在这里。如果我调用QString::toStdString

QString s = "testtesttesttesttesttest";
const std::string &temp = s.toStdString();

程序后来在std::string析构函数处崩溃。

__CLR_OR_THIS_CALL ~basic_string()
    {   // destroy the string
    _Tidy(true); // <---- It crashes on this line.
    }

一开始我以为这是内存损坏,但即使 main() 只包含这两行代码也会发生。是否有人知道为什么会发生这种情况,以及如何修复它?

我的 Qt 版本是 4.8.1


string temp = s.toStdString(); 也会发生同样的事情,只是因为 toStdString() 返回的临时变量的析构函数会立即被调用,所以它会更早地发生。我该如何查看我正在使用的 Qt 版本?我应该去哪里看?这个项目是由其他人设置的,我没有在 Visual Studio 中使用 Qt 的经验,只有在 Qt Creator 中使用的经验。 - sashoalm
1
尝试这个:std::string stdUtf8 = qs.toUtf8().constData(); - Najzero
我也遇到了同样的问题!最后我只是调用了 toLocal8Bit。 - Min Lin
@RedX 我找到了我的 Qt 版本 - 它是 4.8.1。这就是 qVersion() 返回的内容。 - sashoalm
好的,至少你有最新的Qt版本。你是自己编译的还是使用了网站上的二进制文件?如果是自己编译的,你启用了STL支持吗? - RedX
显示剩余3条评论
3个回答

12
你的Qt动态链接库需要编译使用STL支持和与代码完全相同的C运行时库。看起来你同时使用了两个不同的CRT,这会将Qt创建的对象从一个堆放到另一个堆中,导致出现问题。
请使用Dependency Walker检查DLL使用情况!

1
从DependencyWalker(“Profiling”)启动您的应用程序,查看加载了多少个MS-CRT。如果超过一个,则有很大机会遇到问题。 - Jens
那将会检测到不同的动态CRT。 - drescherjm
MSVCR (80|90) D.DLL怎么样? - Jens
1
我建议在调试器中查找,如果加载了多个msvc运行时库的版本。如果您使用Visual Studio启动(或附加)进程,请打开模块窗口。它列出了所有已加载的DLL和可执行文件。如果它列出了多个这样的DLK,则可能是原因。DependencyWalker很有用,但不太可靠。真正的恐怖是Windows SideBySide管理器,它决定将使用哪些Dlls。 - RED SOFT ADAIR
我通过将编译器选项“/MTd”更改为“/MDd”来解决了问题。 - hasan
显示剩余5条评论

3
可能的原因是你的运行库是“多线程 (/MT)”的,需要更改为“多线程 DLL (/MD)”(如果你在发布版本上)。
如果你在调试版本上,请从“多线程调试 (/MTd)”更改为“多线程调试 DLL (/MDd)”。
如果你有奇怪的Qt编译,解决方案应该相反。
你会发现在“配置属性-> C/C++ -> 代码生成 -> 运行库”中。

这真的帮了大忙!我将C++标准库静态链接了,但是Qt的DLL文件链接到了系统的C++可再分发DLL文件,这意味着所涉及的std::string是由可再分发的DLL文件分配的,然后由静态链接的DLL文件删除。 - undefined

0
我尝试用不同的方法解决这个问题。我从Visual Studio创建了一个新项目,测试代码在那里没有崩溃。通过使用WinMerge检查*.vcproj文件之间的差异,我发现导致崩溃的原因是项目中关于运行时库的一些自定义更改。这是由WinMerge创建的补丁,其中包含最小的差异,可以重现崩溃:
112c112
<               RuntimeLibrary="3"
---
>               RuntimeLibrary="1"
126a127,128
>               LinkLibraryDependencies="true"
>               UseLibraryDependencyInputs="false"
127a130,131
>               IgnoreAllDefaultLibraries="false"
>               IgnoreDefaultLibraryNames="msvcrtd.lib"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接