MemoryLeakIndicator
Loading...
Searching...
No Matches
MemoryLeakIndicator 0.0.2

Introduction

If there are memory leaks again, just link the DLL from the MemoryLeakIndicator to the project (I use the MemoryLeakIndicator only in debug mode).

In the main file include MliForMain.h, in the implementation files where something is instantiated with new, after all other includes only the MilDebugNew.h.

In the respective project the MilNewDelete.cpp must be compiled as well.

The English text was translated with the support of www.DeepL.com.

Motivation

I use with Visual Studio on Windows the crtdbg.h to get memory leaks displayed.

See also
https://github.com/MicrosoftDocs/visualstudio-docs/blob/main/docs/debugger/finding-memory-leaks-using-the-crt-library.md

Unfortunately, the file name and the line number are only displayed in the Visual Studio output-window when using malloc, but not when using new. In the case of memory leaks caused by a new, only the address and the data are displayed. While it is possible to assign the value from the curly brackets to the variable _crtBreakAlloc in the hope that the program stops at the place where the non-deleted object is instantiated. But this is unfortunately not always reliable (e.g. with DLLs), since if necessary always another memory location is taken.

Finding the causing instructions in the source code is sometimes difficult. I would like to have the file name and the line number as a hint.

implementation

If there are memory leaks again, just link the DLL from the MemoryLeakIndicator to the project.

In addition, the source file MilNewDelete.cpp (with the overloaded operators new and delete) must also be compiled in the project.

This also applies to self-created DLLs if memory leaks are to be detected there.

In the main file include MliForMain.h, in the implementation files where something is instantiated with new, after all other includes only the MilDebugNew.h. I enclose this with a preprocessor statement such as:

#if defined _MSC_VER && defined _DEBUG_MEMORY_SPY
...
#endif
Note
It is not crowned with success to take over all sources of MemoryLeakIndicator into the own project, thus not to use the DLL.

Example

Here is a small example:

1 #if defined _MSC_VER && defined _DEBUG
2 // detect Memory-Leaks
3 #define _CRTDBG_MAP_ALLOC
4 #include <crtdbg.h>
5 #endif
6
7 #include <iostream>
8 #include <string>
9 #include <conio.h>
10 #if defined _MSC_VER && defined _DEBUG_MEMORY_SPY
11 #include <MliForMain.h>
12 #endif
13 //-----------------------------------------------------------------------------
14 class MyClass
15 {
16 private:
17 int * m_piT1;
18 public:
19 MyClass( int i )
20 {
21 m_piT1 = new int (i);
22 };
23 ~MyClass()
24 {
25 // Oh, m_piT1 forgot to delete
26 //delete m_piT1;
27 };
28 };
29 //-----------------------------------------------------------------------------
30 int main(int argc, char *argv[])
31 {
32 #if defined _MSC_VER && defined _DEBUG
33 // Displays memory leaks when there are any...
34 _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
35 // Comment out next line with number from { } -> e.g..: "{173} normal block at 0x00D01C78, 10 bytes long."
36 //_crtBreakAlloc = 172;
37 // Is unfortunately not always (e.g. with DLLs) reliably, because if necessary other memory location.
38 #endif
39
40 #if defined _MSC_VER && defined _DEBUG_MEMORY_SPY
42 #endif
43
44 // Examples:
45 MyClass * t_pClass = new MyClass( 1 );
46 //delete t_pClass;
47
48 int * t_piLeak = new int( 2 );
49 //delete t_piLeak;
50
51 char * t_szLeak = new char[100];
52 //delete[] t_szLeak;
53
54 #if defined _MSC_VER && defined _DEBUG_MEMORY_SPY
55 // Display memory leaks
57 #endif
58 std::cout << "press any key . . .";
59 _getch();
60 return 0;
61 }
62 //-----------------------------------------------------------------------------
const TiOutput OUTPUT_TRACE
Definition MemoryLeakIndicator.h:186
void __mem_leak_indicator_export_dll finishMemoryMonitoring(MemSpy::TiOutput iOutput=MemSpy::OUTPUT_CONSOLE)
const TiOutput OUTPUT_CONSOLE
Definition MemoryLeakIndicator.h:173
__mem_leak_indicator_export_dll MemSpy::LeakMap * activateMemoryMonitoring(MemSpy::TbExceptionMode bExceptionMode=MemSpy::THROW)

Since the parameters MemSpy::OUTPUT_TRACE and MemSpy::OUTPUT_CONSOLE were passed to the MemSpy::finishMemoryMonitoring(...) function, at the end of the example program, the memory leaks are displayed in the console and in the VisualStudio output window.

Der Thread 15572 hat mit Code 0 (0x0) geendet.
Memory leaks detected! *
Memory leak in 1313691209200, file D:\Projekte\C++\Src\MemoryLeakIndicator\source\main.cpp, line 45
Memory leak in 1313691165808, file D:\Projekte\C++\Src\MemoryLeakIndicator\source\main.cpp, line 21
Memory leak in 1313691166000, file D:\Projekte\C++\Src\MemoryLeakIndicator\source\main.cpp, line 48
Memory leak in 1313691152224, file D:\Projekte\C++\Src\MemoryLeakIndicator\source\main.cpp, line 51
"MemoryLeakIndicatorDllTestd.exe" (Win32): "C:\Windows\System32\kernel.appcore.dll" geladen.
"MemoryLeakIndicatorDllTestd.exe" (Win32): "C:\Windows\System32\msvcrt.dll" geladen.
"MemoryLeakIndicatorDllTestd.exe" (Win32): "C:\Windows\System32\rpcrt4.dll" geladen.
Der Thread 10624 hat mit Code 0 (0x0) geendet.
Der Thread 17076 hat mit Code 0 (0x0) geendet.
Detected memory leaks!
Dumping objects ->
{172} normal block at 0x00000131DE182F60, 100 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
{171} normal block at 0x00000131DE186530, 4 bytes long.
Data: < > 02 00 00 00
{170} normal block at 0x00000131DE186470, 4 bytes long.
Data: < > 01 00 00 00
{169} normal block at 0x00000131DE190DF0, 8 bytes long.
Data: <pd 1 > 70 64 18 DE 31 01 00 00
Object dump complete.
Das Programm "[15928] MemoryLeakIndicatorDllTestd.exe" wurde mit Code 0 (0x0) beendet.
Note
If you create objects in modern C++ projects and pass them on if necessary, you do not use simple pointers if possible, but smart pointers like std::unique_ptr or std::shared_ptr.As a rule, the specifications of RAII should be followed.
See also
https://docs.microsoft.com/en-us/cpp/cpp/object-lifetime-and-resource-management-modern-cpp?view=msvc-170
https://docs.microsoft.com/en-us/cpp/cpp/how-to-create-and-use-shared-ptr-instances?view=msvc-170

Limitations

I failed to overload the new (std::nothrow). When dealing with custom code, this new operator must either be modified for this purpose (without std::nothrow), or MilDebugNew.h is not included.
Every now and then, especially in multi-threaded applications, the MemoryLeakIndicator shows fake memory leaks. These are recognizable if you run the application in debug mode using crtdbg.h and there is no additional output in the output in the VisualStudio output window such as:

Detected memory leaks!
Dumping objects →
{172} normal block at 0x00000131DE182F60, 100 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
...


Trials with MinGW and GCC have also failed for me; only works with VisualStudio C++. If anyone is willing to adapt MemoryLeakIndicator to other compilers, I'd appreciate it.

License

MemoryLeakIndicator is free software:

GNU Affero General Public License Usage
You can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
Please review the following information to ensure the GNU Affero General Public License version 3 requirements will be met: https://www.gnu.org/licenses/agpl-3.0.en.html

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.