Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct
Problem on windows with Qt-based DLL
Hi all, i have created a simple DLL (template vclib) on windows XP using VS2008 and QT 4.6.3 and compiled it in release mode
then i create a simple application (also Qt 4.6.3 on XP, VS2008) and link it against the DLL. If i try to run the app in Debug mode i get heap corruption as soon i do something like:
@qDebug() << mDllPtr->methodReturningAQString();@
from what i've been able to gather the DLL is linked against the Multi-threaded DLL C runtime (/MD compile switch) while the app with the Multhreaded DLL Debug runtime (/MDd compile switch). Probably the returned QString gets de-allocated in the app (with the debug run-time) and that cause a Heap corruption. (Try declaring the method static for a 100% failure).
Obviously using a debug-compiled DLL gives no issues and also compiling the testapp in "release" mode works. (using a "release" app with a "debug" DLL still gives problems)
How can i distribute to customers just a "release" DLL and still allow them to create and debug their own applications?
Dlls and executables must use the smae Heap options (/MD, /MDd, /MT, ...). But it is possible to enable debugging in release dlls (C++ AND linker options).
Goto Project Property Pages
==> C/C++ / General / Debug Information Format ==> program Database (/Zi)
==> Linker / Debugging Generate Debug Info ==> Yes (/DEBUG)
or use the release heap option for your debug build (/MD).
Same applies to the qt dlls you use. For debugging, you normally link to QtCore4d.dll, for release to QtCore4.dll. These MUST also be the same.
Hi Gerolf, thanks for your reply, as for your two suggestions:
- generating program databases and linker debug info for the release build is not an option, since my company does not want to provide debug symbols or other debug info to customers.
- using /MD on the app (compiled in debug) to link with the library (compiled in release with /MD active by default) does not change a bit: still heap corruption
If you say this mixing can NEVER occur, under ANY circumstances, that would mean that is impossible (under windows) to provide customers with just "release" builds. Is this correct?
P.S. just out of curiosity (i am not very knowledgeable on this)... in a project i use Intel's IPP libraries, those are release builds... how come i can compile my project with debug and release build of the app? Do they use some kind of trick? Your reasoning would not apply to this case as well?
I think, 1 is the options to use. I never said, you should deliver your debug info. But the customer can create his exe in release mode with debug info. Then he can debug his app. We do the same.
And we also never deliver our pdbs :-)
Gerolf i just updated my post while you were replying :)
i don't get your last post though... :)
Test app is already compiled in debug so it will create automatically all that should be needed for its debug right? (in fact i can breakpoint in it)
if i release also "debug" build of the library (although without PDBs) it will still use the /MDd runtime (that is un-optimized upon Microsoft documentation) and also i would need to redistribute (and i cannot since license does not allow it) the debug runtime for the VS version i used to compile the library. Is this correct?
thanks again :)
I'm not sure about licences in this case. The fact is, if you have a non memory neutral interface of you dll (which means you allocate memory in one binary and free it in another binary) those two binaries MUST use the same heap allocations. The heap allocations in MSVS builds are done b y the msvcrt*.dlls which are defined by /MD /MDd /Mt or /MTd. If one uses one and the other another it will crash if memory is given over binary boundaries and freed there.
If you have a pure C interface which uses some semantics like
Example (even this function does not work this way in reality :-))
char* buffer = 0;
int nLength = ::getenv("MyVar", buffer, 0);
++nLength; // add ending \0
buffer = new char[nLength];
int nLength = ::getenv("MyVar", buffer, nLength);
this means call the function once with buffer length 0 to get the needed buffer, allocate it and call again, it's no problem, as the memory is always created and freed in the same binary.
In our release builds, we use /MD and add debug info. so we can debug if we need but we never deliver the pdbs.
Thanks for giving a hand, i tried setting /DEBUG and /Zi in the library release build but nothing changed in the testapp result (still crash).
i uploaded a simple testcase at http://rapidshare.com/files/456023127/testcase.rar
no matter what setting i put on testdll (release build), testapp always has issues (in debug)