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

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.

Related

What is Different Between "MFC DLL" and "Console Application DLL"?

What is the difference between creating a MFC DLL from Visual Studio wizard and creating C++ Console Application and changing the configuration type to DLL instead of .exe?
You can surely figure out how to change a console application to dll type, but it's recommended to use the non-MFC DLL project template.
One major difference between a non-MFC and a MFC Extension DLL is that it would allow sharing resources like dialog templates or bitmaps to MFC appliactions by calling
// MFC extension DLL one-time initialization
AfxInitExtensionModule(PROJNAMEDLL, hInstance);
// Insert this DLL into the resource chain
new CDynLinkLibrary(Dll3DLL);
in DllMain(). Other benefits are that you can use MFC (CObject-derived) classes that sit in the dll and that the MFC Extension DLL can share the memory address space with the calling instance, meaning that two apps loading the same extension DLL will only share the code but won't interfere with allocated data.
Note that you need the "shared MFC DLL" project setting to use extension DLLs. Linking MFC statically into your project won't work. So extension DLLs aim at sharing code among different apps that run simultaneously, for example, but only use the code memory once. This way of code reuse was one intention at least when extension DLLs were introduced, but in the real world different apps tend to use different versions (dll hell, side-by-side). Speaking of:
One good use of an extension DLL is to customize an app (branding, localisation) just by installing differend versions of a dll.
Further reading: https://learn.microsoft.com/en-us/cpp/build/extension-dlls
According to Creating an MFC DLL Project it states:
An MFC DLL is a binary file that acts as a shared library of functions that can be used simultaneously by multiple applications. The easiest way to create an MFC DLL project is to use the MFC DLL Wizard.
This article Kinds of DLLs also states:
Using Visual Studio, you can build Win32 DLLs in C or C++ that do not
use the Microsoft Foundation Class (MFC) library. You can create a
non-MFC DLL project with the Win32 Application Wizard.
The MFC library itself is available, in either static link libraries
or in a number of DLLs, with the MFC DLL Wizard. If your DLL is using
MFC, Visual Studio supports three different DLL development scenarios ...
I believe the above explains the difference:
One version of the DLL exposes the MFC library.
One version does not.
That is my understanding.
Other related article: Create C/C++ DLLs in Visual Studio
An MFC DLL is a dynamic library that uses MFC components and the MFC runtime. This means that an MFC dynamic library usually requires the MFC support libraries along with the MFC runtime. To compile an MFC DLL requires the MFC include files and the MFC directives.
When you use the Visual Studio Wizard to create an MFC DLL all the compiler, linker, and other settings and options needed to create an MFC DLL are all generated for you along with an MFC DLL stub.
A Console Application is an application that uses the C++ Runtime from a console window.
When you use the Visual Studio Wizard to create a Console Application all the compiler, linker, and other settings and options to create a Console Application are all generated for you with a Console Application stub which is typically a Hello World type of application with a main() that contains a printf().
The source code for a DLL has required structure for a DLL main entry point that is different from the required structure for a Console Application main entry point. See the Microsoft article DllMain entry point which has this example source code:
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved ) // reserved
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
So the differences between an MFC DLL and a Console Application involves a number of areas:
the structure of the source code
the include files used in the compile
the libraries used in the link
the options used in the compile
the options used in the link
Changing the configuration type does not modify the source code or include files specified in the source code. Nor does changing the configuration type change all of the necessary compiler and linker options and property settings that need to be changed.
See this Microsoft article, DLLs and Visual C++ run-time library behavior, that discusses the structure of DLLs and their run time behavior which provides an idea as to the differences between an EXE and a DLL.
An Application (executable) is a module that can be run. It contains one entrypoint, the main() (console) or WinMain() (windows GUI) function. A running instance of an executable is called a "process" in Win32.
A DLL is a library, intended for use by other applications. It is loaded at runtime - "dynamically", hence the name. DLLs contain no main entrypoint, instead they "export" functions or even classes and data. Lacking a main entrypoint, DLLs cannot be run stand-alone, instead they are "loaded into a process's (application's) address-space". The process can use their exported items. It is a good way to implement commonly used operations, for example a company's "development environment" or "foundation" - SDKs are typically implemented as DLLs.
MFC is a C++ library containing GUI (and other) classes and functions, largely (but not exclusively) wrapping Win32 objects. An application or DLL can be using the MFC library, or not.
As for your question, creating a console application and then changing it to DLL makes no sense. The Wizard will create a main() function, which you will have to manually remove. And finally you will have what, a normal DLL... You can simply create a DLL from the start, whether it will be using MFC or not.
EDIT:
According to the documentation from Microsoft:
Each process provides the resources needed to execute a program. A process has a virtual address space, executable code, open handles to system objects, a security context, a unique process identifier, environment variables, a priority class, minimum and maximum working set sizes, and at least one thread of execution. Each process is started with a single thread, often called the primary thread, but can create additional threads from any of its threads.
So yes, processes need to contain at least one thread - terminating the primary thread also terminates the process. Furthermore, an executable must contain an entry point, it's what the primary thread will execute and return a value to the system. It's actually impossible to build an executable without a main()/WinMain() function, it will generate Linker Error LNK1561:
entry point must be defined
The linker did not find an entry point, the initial function to call in your executable. By default, the linker looks for a main or wmain function for a console app, a WinMain or wWinMain function for a Windows app, or DllMain for a DLL that requires initialization. You can specify another function by using the /ENTRY linker option.
As for DLLs, the term dynamic "linking" is indeed used by MS, however only to highlight the differences to static linking (what most developers consider linking). It's not linking in the usual way, ie resolving externals, changing symbol names to addresses, performing fixups and the like. A DLL has no unresolved externals and the so called "linking" means just locating exported items from the loaded DLLs (in the case of using an import library they are also assigned to local functions) - the linker is not involved in the procedure. Further information here.
Therefore I don't think that there was something "slightly wrong" in what I had posted above, and certainly not "literally everything".
As for whether my answer should be considered useful or not, I think I was right to suggest not creating an executable and changing it to a dll. An MFC DLL is a DLL "based on" (using) the MFC library - this was clear in my first post. The OP didn't ask about MFC extension DLLs particularly.

Crash when deleting CStringArray*

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

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.