I have a MFC project that uses libpqxx. All settings are default.
Release mode is working properly as i expected. But when i switch to Debug mode, it shows an exception and says Debug Assertion:
The most interesting thing is, If I use Shared DLL instead of Static (on Debug of course) it works!
Basicaly, Debug with Static Library shows this exception/error. If i switch to Shared DLL it works again. Of course i can use shared as debug and static as release but Is this the right thing?
Note: This project is base and fresh. I did not changed any config from Configuratrion Manager.
Any suggestion?
Alright, I am not sure if libpqxx uses MFC or not (and which one?). I suspect that you are allocating some memory from one heap, and de-allocating it from another heap. Mixing MFC versions, as well as Static/non-Static mixture of MFC will cause this assertion.
Do not treat it as working on Release build! It is just not defending itself (i.e. now showing any assertion message). Your best bet is to locate the cause of this problem, and first one goes by looking-up the call stack (hit Retry on this assertion dialog).
See, if libpqxx depends on MFC, or it disallws mixing Static version of MFC. You can either see the documentation of libpqxx, and/or use Dependency Walker to see if library is using MFC.
Related
Crashing Code
The following code makes my program crash (program exits) by heap corruption when the third line (the 'delete' command) is called:
1: CStringArray* pStringArray = new CStringArray();
2: ClassInDll::addToStringArray(_T("asdf"), *pStringArray);
3: delete pStringArray;
with
1: ClassInDll::addToStringArray(CString s, CStringArray& sa){
2: sa.Add(s);
3: }
addToStringArray() is static
Be aware that this is not actually my code, but simply the minimum with which I can reproduce the error. It is reproducible with CArray<CString> as well.
I verified, that the heap corruption does indeed not happen before that code line via
gflags /p /enable MyExe.exe /full
StackTrace:
What seems to be the problem
Dll dependency
MFC source
1
CStringArray creation
MyExe.exe > MFC
...\Microsoft Visual Studio 10.0\VC\atlmfc\src\mfc\array_s.cpp
2
Internal array allocation
MyExe.exe > MyDll.dll > MFC
...\Microsoft Visual Studio 10.0\VC\atlmfc\include\afxcoll.inl
3
Deletion
MyExe.exe > MFC
...\Microsoft Visual Studio 10.0\VC\atlmfc\src\mfc\array_s.cpp
The fact that the internal array is not deleted the same way it was created is probably the error. (Please correct me if I'm wrong)
Project Settings
I made sure that the same MFC settings are used in MyExe.exe as well as MyDll.dll, i.e.:
Use of MFC
Use MFC in a Shared DLL
Use of ATL
Not using ATL
Character Set
Use Unicode Character Set
I test in debug mode, so there is no optimization.
Question
MyDll.dll is not the only dll that is loaded, and there is too much going on with project dependencies (to third party dlls etc), so I cannot make all this part of my question.
So my questions boil down to:
Is my assumption correct that array_s.cpp and afxcoll.inl are not compatible with one another?
What makes one piece of code call array_s.cpp, and the other call afxcoll.inl?
What else could be the problem?
I have tried turning it off and on again ;)
Thank you in advance!
Update
PaulMcKenzie pointed out that this is the case if I build against different CRTs which was the case. One was "Multithreaded Debug DLL", the other was "Multithreaded DLL". Still, the problem persists, after making both equal. This page states that if using VS 2015 and above with Windows 10 and having project settings so that the same runtime library is used, the same CRT library is used at runtime (and therefore should use the same heap, right?).
I've made sure, that every entry within "Project Properties -> C/C++ -> Code Generation" is exactly the same in the exe and dll.
Passing MFC objects (even via pointers) between modules (EXEs and DLLs, or different DLLs) is a very tricky business. If you're simply using classes in the DLL, then you should (at the very least) be using the AFX_MANAGE_STATE macro (see here) in the DLL.
However, if your DLL is defining its own MFC-derived classes (your ClassInDll seems to be such), it should really be built as an MFC Extension DLL.
The whole process of building extension DLLs (and even using the 'regular' MFC DLLs) is rather too broad for me to provide any usable source code for you here. But, from the second link above, the following section is likely relevant to the problem(s) you are seeing (bold italics are mine):
Memory Management
MFCx0.dll and all MFC extension DLLs loaded into a client
application's address space use the same memory allocator, resource
loading, and other MFC global states as if they were in the same
application. This is significant because the non-MFC DLL libraries and
the regular MFC DLLs do the exact opposite and have each DLL
allocating out of its own memory pool.
If an MFC extension DLL allocates memory, that memory can freely
intermix with any other application-allocated object. Also, if an
application that dynamically links to MFC fails, the protection of the
operating system maintains the integrity of any other MFC application
sharing the DLL.
Similarly other global MFC states, like the current executable file to
load resources from, are also shared between the client application
and all MFC extension DLLs as well as MFCx0.dll itself.
It turned out that release and debug dlls were both being loaded (because of another dll):
msvcr100.dll
msvcr100d.dll
msvcp100.dll
msvcp100d.dll
The "modules" window sure does help, if you only know that you should look there.
Thanks to PaulMcKenzie and IInspectable for leading me into the right direction.
I need to add Common Language Runtime Support (/clr) to my mfc dll project in order to use managed code in it.
I have do some setting for the all projects according to how to compile MFC and ATL Code By Using /clr from msdn.
I have done a lot of testing. But still failed to run my application although I only add the /clr support to the project without adding any managed code.
See below for details:
The exception, call stack, output information, the difference of output information and dependency dll between using and without using /clr please see Exception Detail
I can't get any useful information from call stack. I don't know even where to add the break point for debugging. Anyway, it's too later to add the break point at the InitInstance() of the application.
It seems the exception caused by loading dlls according the output information. But I don't know the really reason.
Otherwise I have downloaded a sample solution from msdn see Sample about Using /clr in MFC. The sample contains a mfc application calling a mfc dll with /clr support. And it works well. When I add my mfc dll(with /clr support) into this sample, it can work well too. I really don't down why it can't work in my solution. I have checked the property setting of my project compare with the sample solution. There seems nothing special.
I do need help, any suggestion?
Thank you all.
I have solved the issue by delaying loaded the dll that cotaines /clr support in the project calling it. See Set Delay Loaded DLL for how to delay dlls. It seems the exception caused by the chaotic unmanaged and managed initialization.
"Unmanaged and managed initialization is performed in two separate and distinct stages. Unmanaged initialization takes place first (via DllMain), and managed initialization takes place afterwards, through a .NET-supported construct called a .cctor. " See Initialization of Mixed Assemblies for details
I am writing a program using OSG and I would like to step through it to see how stuff works, change a few lines and debug again. However every time I need to load a file using osgDB plugin for openflight. The debug version of the plugin works quite slow. I have no intention of debugging the plugin itself, so I figured I might as well use the release dll. I read that I can do this as long as there are no memory allocation in program and freeing in dll or visa versa and if the dll was designed to avoid problems that might occur with release/debug mixing. I'm not sure if osgdb_openflight.dll was designed like that.
My question: can I use the release plugin dll in my debug build, and how can I make my program use it?
UPD: I achieved my goal following the #XenonofArcticus's advice.
Some additional thoughts on the topic for the sake of better understanding:
I also tried to simply rename the release dll, so it would get loaded in the debug build. (I thought this would work, because I usually use release dlls in debug builds - Windows's, SQL's and other 3rd party dlls, that do not come with debug info. Also see Igor Tandetnik's comments on this question). It did and the program didn't crash, however it also didn't load the file. Apparently this particular dll wasn't designed to be used in debug builds. Any other explanation?
I'm not sure you're going to achieve what you want trying to mix debug and release. However, perhaps it would work to build a release with debug symbols target? This can allow you to do SOME debugging, but it's still a release build and behaves like one.
I'm noob in C++ world and I'm facing a weird behaviour. I use Visual Studio 2010.
The context: I decided to use wxWidget for GUI.
For this, I had to change in my project properties the following settings:
C/C++ > Code Generation > Runtime library > /MTd (previously it was /MDd)
General > Use of MFC > Use MFC in a shared DLL (previously it was Use MFC in a static library)
Since these changes, all my delete[] on CStringArray* crash my app.
I try to change delete[] by delete but it causes a huge memory leak.
I don't understand why theses changes in project settings generate this difference of behaviour.
EDIT:
The output message is:
HEAP[xxx.exe]: Invalid address specified to RtlValidateHeap( 002B0000,
002BDE54 ) Windows has triggered a breakpoint in xxx.exe.
This may be due to a corruption of the heap, which indicates a bug in
xxx.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while xxx.exe has focus.
I have read that:
The CRT libraries use weak external linkage for the new, delete, and
DllMain functions. The MFC libraries also contain new, delete, and
DllMain functions. These functions require the MFC libraries to be
linked before the CRT library is linked.
So I tried to add in Properties> Configuration Properties> Linker > Input > Ignore Specific Default libraries: nafxcwd.lib;libcmtd.lib;
no changes.
In the call stack, I see that it's CStringArray::vector deleting destructor that is invoked.
So, I give up. I have left to much time on this problem.
I think that there is an underlying issue that spread when I'm deleting a pointer.
I'm gonna try Qt...
For some reason the integrated debugger is causing an error as soon as I make reference to a third party vendor's dll class. This same code runs when it is built and ran as a release, stand alone. The two properties for debug and release should be the same as I have not really altered them. I added the lib file to the path for both builds. I simply have:
ClassNameFromDll blah;
When it gets to here, I get this exception:
Unhandled exception at 0x78a3f623 (mfc90ud.dll) in MTGO SO Bot.exe:
0xC0000005: Access violation reading location 0xf78e4568.
It occurs in: afxtls.cpp, line 252.
This is an MFC app, but I am not really using any MFC other than a very simple gui which fires off an event that is all win32. I am using Visual Studio 2008 Express.
Looking at the atltls.cpp file from my VC9 install, the crash is occurring here:
inline void* CThreadSlotData::GetThreadValue(int nSlot)
{
EnterCriticalSection(&m_sect);
ASSERT(nSlot != 0 && nSlot < m_nMax);
ASSERT(m_pSlotData != NULL);
ASSERT(m_pSlotData[nSlot].dwFlags & SLOT_USED); // <== crash
// ...
}
So the reason the crash doesn't occur in release build is because the ASSERT() is a no-op in that build. I'm not familiar with ATL's use of thread local storage, but this assertion indicates that something is asking for a value in a slot where nothing has been stored yet.
Whether the initialization of that TLS slot is your responsibility or the 3rd party DLL's responsibility, I don't know.
It looks like GetThreadValue() has some additional protections such that it'll return a NULL pointer in the release build for an uninitialized slot (though I'm not sure that this would be guaranteed) - I'd bet that the 3rd party DLL relies on that behavior (ie., it checks for a NULL return) so no crash occurs in release builds. Note that the vendor might be using the CThreadSlotData class indirectly (the stack trace would give a clue about this), so they might not be aware of its expectations.
engaging psychic debugging
The fact that it runs in release mode fine and crashes in debug mode leads me to believe that you've somehow managed to reference, specifically, the release version of that DLL (mfc90u.dll), rather than referencing the library itself and allowing the linker to decide which version to import.
You may not be using MFC for anything in this app, but if it's building as an MFC application, you will get all of the MFC stuff whether you want it or not (which means you also have to solve the MFC dependency problem and ship the MFC DLLs with your app).
Do you have a stack trace you can post? It might have some helpful information.
If the 3rd party DLL is still actively supported by the vendor, then the first thing you should do is see if you can have the same problem occur with a very simple program that you can send to the vendor and ask them to fix it.
If the vendor is not available or responsive enough:
If you have source of the 3rd party DLL and can easily build your own version, you have probably the best way to debug this (short of getting the vendor to support you). Even if you cannot easily build a source-debuggable DLL, you can trace into the constructor's assembly instructions and use the source as a map to help you understand what's going on.
Even if you don't have source for the 3rd party DLL then I think the best course of action is to trace through the constructor for ClassNameFromDll to try to figure out whats going wrong. It might help to compare the instructions path in the Debug build vs. the Release build.
MFC source is distributed with MSVC (probably not with the Express version, but I think with all other versions) so when you get in to the MFC DLL's code you might find the source to be useful in helping to figure out what's going on.