
Abstract
Memory is a very important aspect for an application to run. Applications that leak large amounts of memory or leak progressively may display symptoms ranging from poor (and gradually decreasing) performance to running out of memory completely. Worse, a leaking program may use up so much memory that it causes another program to fail, leaving the user with no clue to where the problem truly lies. In addition, even harmless memory leaks may be symptomatic of other problems.
When an application is very big, it could have 100+ files and 1000+ functions and it would be tough to find memory leaks in the application, so we can use the CrtDbg
Library APIs to find the memory leaks in that application.
For memory leak detection, we have so many tools available in the market, but you need to pay a lot for them. This article talks about a C Runtime Library which is free and available with all Windows OSs, and is called the CrtDbg
Library. This library provides APIs which can be used to detect memory leaks.
Audience
Win32/Win64 developers who want to detect memory leaks in their applications.
Memory Leak Samples
class test
{
public: test()
{
a = new int;
}
~test()
{
delete a;
}
private:
int *a;
};
test *t = new test[10];
{
char* str = new char[20];
strcpy(str,"memory leak");
}
Introduction
Memory Allocation on Stack
int number = 10;
Whenever a number variable goes out of scope, the memory allocated for the variable will be deallocated automatically.
Memory Allocation on Heap
int * number = new int[10];
The above line allocates 10 integer sizes on the heap (40 bytes if the integer size is 4 bytes), and we have to call the delete
function to deallocate the memory allocated on the heap. delete [] number
is required to delete the memory allocated on the heap in the above example. Sometimes, we forget to call delete
for the variables allocated on the heap, and we can use C Runtime Library (CRT) functions to find the leaks in a given code.
Using the Code
We can use CrtDbg
library functions to detect the memory leaks in our application.
The technique for locating memory leaks involves taking snapshots of the application's memory state at key points. The CRT library provides a structure type, _CrtMemState
, which you can use to store a snapshot of the memory state:
_CrtMemState s1, s2, s3;
To take a snapshot of the memory state at a given point, pass a _CrtMemState
structure to the _CrtMemCheckpoint
function. This function fills in the structure with a snapshot of the current memory state:
_CrtMemCheckpoint(&s1);
After calling _CrtMemCheckpoint(&s1)
, code can be written in which we can detect the memory leak. (_CrtMemCheckpoint
can be used anywhere in the code.)
After writing your code, use _CrtMemCheckpoint( &s2 )
to take another snapshot of the memory at that time; after that, you can call _CrtMemDifference(&s3, &s1, &s2)
.
_CrtMemDifference
compares two memory states s1
and s2
, and returns their differences (debug version only). _CrtMemDifference(&s3, &s1, &s2)
will return 0
if there is no memory leak between the s1
and s2
memory checkpoints, and returns 1
if the code written between the checkpoints s1
and s2
has a memory leak.
If _CrtMemDifference
returns 1
, then we can call _CrtDumpMemoryLeaks()
to dump the memory leak. The memory leak will be shown in the Debugger window of the IDE (Visual Studio) with the line number of the memory allocation which has not been deallocated.
If you want the file name and the line number of the memory leak in your application, then overload the operator new macro with another macro which will use the file name and the line number.
#define new new(_CLIENT_BLOCK,__FILE__, __LINE__)
By using the above code, the _CrtDumpMemoryLeaks
function will show the file name and the line number of the memory leak in your application.
And if you want the memory leak information to be logged into a file, then use the following API with the required options.
_CrtSetReportMode
Function prototype:
int _CrtSetReportMode( int reportType, int reportMode );
Report type: _CRT_WARN
, _CRT_ERROR
, and _CRT_ASSERT
_CRT_WARN
: Warning, messages, and information that do not need immediate attention_CRT_ERROR
: Errors, unrecoverable problems, and issues that require immediate attention_CRT_ASSERT
: Assertion failures
Report mode: _CRTDBG_MODE_DEBUG
, _CRTDBG_MODE_FILE
, _CRTDBG_MODE_WNDW
, _CRTDBG_REPORT_MODE
_CRTDBG_MODE_DEBUG
: Writes the message to the debugger's output window _CRTDBG_MODE_FILE
: Writes the message to a user-supplied file handle. _CrtSetReportFile
should be called to define the specific file or stream to use as the destination._CRTDBG_MODE_WNDW
: Creates a message box to display the message along with Abort, Retry, and Ignore buttons._CRTDBG_REPORT_MODE
: Returns reportMode
for the specified reportType
: _CRTDBG_MODE_FILE
, _CRTDBG_MODE_DEBUG
, _CRTDBG_MODE_WNDW
.
_CrtSetReportFile
After specifying _CRTDBG_MODE_FILE
with _CrtSetReportMode
, you can specify the file handle to receive the message text.
Function prototype:
_HFILE _CrtSetReportFile( int reportType, _HFILE reportFile );
So if you want to log a memory leak found in your application to a log file, then create a log file using the CreateFile
Win32 API and then use _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE)
and after that _CrtSetReportFile((_CRT_WARN, FileHandle)
. The file handle will be returned by the CreateFile
Win32 API (which is used to create a file).
Sample Code
int main()
{
_CrtMemState &s1,&s2,&s3;
_CrtMemCheckPoint(&s1);
_CrtMemCheckPoint(&s2);
if (_CrtMemDifference(&s3,&s1,&s2))
{
_CrtDumpMemoryLeaks();
}
return 0;
}
How Can We Avoid Getting Memory Leaks?
Make sure that:
- You correctly use '
new
'/'delete
' and 'new[]
'/'delete[]
' (also 'malloc
'/'free
'). - Pointers don't go out of scope before memory is released.
- If you allocate memory in a loop, you release it in each iteration.
Summary
Memory is a very important aspect to run any application, so avoid memory leaks while writing code by following the above guidelines, and get your code reviewed by other technical members of your team, or use the CrtDbg
library APIs. The CrtDbg
library works only in Debug mode, so you cannot use it to find memory leaks for Release mode applications.
Attached to this article is a sample application which uses CrtDbg
APIs to find memory leaks. This sample application can be opened using Visual Studio 2005. Compile the application in Debug mode and execute it. It will show the memory leaks in the Debugger window of the Visual Studio 2005 IDE.
History
- 17th March, 2010: Initial post
- 19th March, 2010: Article updated