开发者

Returning QVariantList in Visual Studio 2008 crashes

开发者 https://www.devze.com 2023-03-16 13:31 出处:网络
We have a function that converts JSON objects retrieved from a C library to QVariants. All data types work fine---booleans, numbers, strings, objects/maps---except for lists. When the function returns

We have a function that converts JSON objects retrieved from a C library to QVariants. All data types work fine---booleans, numbers, strings, objects/maps---except for lists. When the function returns a list, it crashes on exit of the function due to "invalid address specified to RtlValidateHeap", which I presume means that a double free has occurred.

The following code demonstrates the error:

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!") )

I have seen posts about this, but they all seem to be about Visual Studio 2010 and it not being compatible with the binary version of the Qt SDK. I have tried this with Qt 4.7.3 downloaded from http://qt.nokia.com/downloads/sdk-windows-cpp.

The crash occurs when the list goes out of scope; as long as the return value is propagated back in the call stack, no crash occurs.


Thank you for your answers.

Yes, I am fully aware that the compiler constructs a QVariant when I return another value, but I am certain that the compiler implicitly constructs an equally good QVarint compared to what explicit coding from me would :-)

When installing from the link I provided, libraries for both MinGW and Visual Studio 2008 are installed. I have added \Desktop\Qt\4.7.3\msvc2008\lib to my global lib file search path, and when I run my program, the Visual Studio output window list开发者_JS百科s only DLLs from \Desktop\Qt\4.7.3\msvc2008 as loaded.

The error happens in msvcr90d.dll, presumably when the memory is freed a second time. It is hard to tell, since the stack appears to be destroyed.

The application is a rather large one, with only the GUI written in C++ and the rest being C. Could this be an issue? The program loads both msvcp90d.dll and msvcr90d.dll.


The error turned out to be that the individual projects in the solution linked to static runtimes, whereas the Qt libraries linked to dynamic runtimes.

I looked through the configurations of the 20+ projects as well as those for already built projects not included in the solution but linked to, and it turned out that if even one linked to the C runtime statically, the application would crash.

You change the runtime by opening the properties of the project, navigating to Configuration Properties->C/C++ and selecting Code Generation. The Runtime Library should be Multi-threaded DLL for Release targets and Multi-threaded Debug DLL for debug targets.


Your method signature is

QVariant crash()

You should return a QVariant but instead of a QVariant you are trying to return a QVariantList which is synonym for QList <QVariant>

I don't think you can do this.

You should not even be able to compile this in my opinion. Maybe this is your problem ?


I see a couple of potential issues:

First, the SDK you link to is for the MinGW compiler, not visual studio. You should use the correct SDK for your compiler, or recompile Qt from source. For VS2008 go to this page : http://qt.nokia.com/downloads/ and download "Qt Libraries for Windows - VS2008".

Your code does compile : what happens is it is returning a QVariant which contains a QVariantMap or QVariantSet. The compiler is constructing a QVariant for you. What your code is actually doing is this :

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
}

This should work OK - I just compiled it here and it works for me. You should just need to check the type of the QVariant when you use it (e.g. calling toString() on the returned QVariant will return an empty string as it is the list you are calling it on, not the QVariant in the list)


Make sure the Runtime Library option in C/C++ Code Generation is set to Multi-threaded Debug DLL (/MDd) or Multi-threaded DLL (/MD) respectively for Debug and Release. Some Qt types as QVariantMap, QVariantList, QModelIndexList are probably allocated with /MD (in Qt's dll) and when they are deallocated with /MT (in the app) I think this causes the crash. This can also fix the crash on QString::toStdWString(). In order for this to link maybe the Ignore All Default Libraries should be set to No and Ignore Specific Library should not mention crt dlls used by Qt.

0

精彩评论

暂无评论...
验证码 换一张
取 消