Understanding Visual Studio Memory Leaks

  1. Place the following code near the beginning of the file containing your main function:

    #ifdef _MSC_VER
    #define _CRTDBG_MAP_ALLOC  
    #include <crtdbg.h>
    #define VS_MEM_CHECK _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    #else
    #define VS_MEM_CHECK
    #endif

  2. Put the following C pre-processor macro at the beginning of your main code:

    int main(int argc, char * argv[])
    {
       VS_MEM_CHECK
       // Your program...
       return 0;
    }

  3. If you get something like the following when your program exits, YOU HAVE A MEMORY LEAK! You are required to remove all memory leaks.

    The thread 0x34bc has exited with code 0 (0x0).
    Detected memory leaks!
    Dumping objects ->
    {149} normal block at 0x00365008, 4000 bytes long.
     Data: <                > 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 
    Object dump complete.
    The program '[4984] Lab 03 - Iterator (nested).exe' has exited with code 0 (0x0).
    

Errors NOT DETECTED by VS_MEM_CHECK

Conditional jump or move depends on uninitialised value(s)

This error would result from a loop or if statement that is dependent on an uninitialized variable (a variable whose value you haven't set). In the example below, notice that the integer x is only set if userInput is equal to true. But then, no matter what, we use x in the for-loop condition, even though it might not be set. This creates problems, because if you don't set the value of the variable, it will be set to some unknown value.

int main()
{
	int x;
	if (userInput == true)
	{
		x = 5;
	}
	for (int y = 0; y < x; y++)
	{
		std::cout << y << std::endl;
	}
}

Invalid write of size n

This error would result if you have written outside the bounds of memory you have allocated. For example, suppose you allocate an array of integers with 5 items, but then try to access the 8th element:

int main()
{
	int* arr = new int[5];
	arr[8] = 100;
	delete[] arr;
}

Mismatched (or Invalid) free() / delete / delete[] / realloc()

This error can have several causes. The most common reason is forgetting to use delete[] with dynamically allocated arrays. In this example, the valgrind error could be corrected by simply adding the square brackets after delete.

int main()
{
	int* arr = new int[5];
	arr[2] = 100;
	delete arr;
}	

This can also occur if you don't correctly delete the memory you've allocated. Anytime you use new, you must delete with delete. Anytime you use malloc, you must delete using free. Attempting to mix and match, will be detected by MEM_CHECK.

int main()
{
	int* myInt = (int*)malloc(sizeof(int));
	*myInt = 5;
	delete myInt;
}

One other thing that can cause this problem is deleting the same thing twice:

int main()
{
	int* myInt = new int;
	delete myInt;
	delete myInt;
}	

Stack overflow in thread

In labs that use recursion, such as BST, you may run into this error. Most frequently this occurs when you don't have exhaustive base cases for a recursive function. Without all the necessary base cases, your recursive function will continually call itself until there is no more memory on the stack to call it.

Segmentation Fault

A segmentation fault generally occurs if you try to access memory that is already reserved by the system. In this class, this most commonly occurs if you try to access a data member of a NULL pointer, like this:

struct Node
{
	int x;
};

int main()
{
	Node* n = NULL;
	n->x = 5;
}