Crash when deleting CStringArray* - c++

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...

Related

MFC: Why does this heap corruption happen? (array_s.cpp / afxcoll.inl)

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.

How to debug program crashing before main()

I'm using QtCreator with the visual studio 2015 kit on windows 8.1 to build a program I developed and tested on Linux, on linux it works correctly, but on windows it's just crashing immediately, and I have no idea what to look for.
The only external libraries, aside from QT I'm using are opengl and glew, so I don't think it's those.
Is there anything that's known to work in GNU C++ but crash immediately in MSVC?
Usually this kind of crashes have absolutely nothing to do with your program. It's an external library linking issue. I had this issue recently with the OpenSplice DDS library. I linked to a library that caused a segmentation fault before anything started. I resolved the issue by linking the pre-compiled libraries 1-by-1, and check each if that fixes the program.
What I recommend you to do is: Remove the libraries and resources you're linking to gradually, until your program starts and prints "Hello world" from the first line of main().
Another way to go is, make a new empty program, and link the same resources you're using in your program. This is easier, as it doesn't involve modifying your program.
This is what I would do.
Start by rebuilding the entire solution or project from a clean state. Just in case this is just some weird dependency issue that resulted in something not getting recompiled. Never hurts.
As Neil said in the comments for the question, the crash is possibly coming from a global variable who's constructor runs before main or WinMain. Are you sure you don't have something declared as "static" or at global scope that might have a constructor?
Now do the following:
Open Visual Studio.
From the menu, select File->Open->Project/Solution...
When the file open dialog pops up, select the EXE produced by Qt
Creator. (That's right - you are opening the EXE as a project). This directory is typically one folder level above the Qt project (..\build-yourapp-Desktop_Qt_5_7_0_MSVC2015_32bit-Debug\debug)
Now press the green arrow to start debugging (menu->Debug->Start
Debugging). If all goes well, your program will fail early and
Now chances are high that the program is not going to run at all under Visual Studio because Qt Creator doesn't copy all the Qt*.dll binaries to your build directory. You'll get a bunch of dialogs popping up saying that "The program can't start because Qt5-XYZ.dll can't be found". This is easily fixed by updating your PATH environment in any of the following way to include your Qt5.x.0\5.x\msvc2015\bin folder to your PATH.
You add it from the command linke and then re-launch devenv.exe from the command line.
You can add it globally from Control Panel->System->Advanced. Then restart Visual Studio from the Windows desktop.
With the EXE debug project open from within Visual Studio, just right click on the project name (not parent solution) and a dialog will popup that allows you to edit startup settings. One of which is the Environment.
And that should do it. From there you can start the debugger on your EXE, set breakpoints as needed, and analyze the call stack on crash.
It's really easy: build all the libraries you use, including Qt, with debug information (those can be release builds as long as the PDB files are generated). Then run your application under a debugger (e.g. F5 under Qt Creator), and it will stop at the point of the crash.
The code that runs before main and is known to cause trouble will be the global object initialization: you're likely running into the static initialization order fiasco.
Another cause for the problem could be stackoverflow. In Linux, the stack size by default is usually 8 MB whereas in Windows it's just 1 MB.
Try to link with /STACK:8388608 switch. If it works, you might consider allocating more data on the heap and stay with the default stack size of 1 MB.

libpqxx throws an exception during DEBUG mode

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.

HEAP CORRUPTION DETECTED after upgrade in vs2008

I have a project that was build in vc++ 6.Now I Upgrade it vs2008 and it build now perfect but when I open it from debug folder it also open but not execute because the related dll are not there.
Now I copied the exe in the other folder and the related dlls and try to open it the pop box open.
Now there are 2 question in my mind that-
is there any file corrupt.
My dlls are the build in vc++6 environment.Should I upgrade the dlls also.
and may be there is another issue.
Please suggest!
Build all projects and solutions in Visual C++ 2008, and carefully remove all higher level warnings (level 1 and level 2, at least).
Run the programs from debugger (in debugging mode - i.e. F5, and not Ctrl+ F5)
Run Debug build only. That too only 32-bit, in which you can edit-and-continue. For this you must enable /DEBUG linker option
Try to narrow down the problem. Do step-by-step debugging and see where it fails. If it asserts, it is good, not bad! Look at the call stack and find the cause.
Don't ignore exceptions, or hide them into try-catch blocks.
stick to the rule:
Memory should be allocated and deallocated in the same module. Namely, donot allocate in dlls and deallocate in exes, vice versa.
You should check that which crt your project are using. Different CRT allocates memory in different ways, and many extra work will be done during the progress.
see:Do (statically linked) DLLs use a different heap than the main program?
Maybe you should reconstruct your codes finally.

Visual Studio Debuging Errors in C++

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.