Skip to content

Instantly share code, notes, and snippets.

Created March 8, 2016 09:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/f41657c289a2547f511b to your computer and use it in GitHub Desktop.
Save anonymous/f41657c289a2547f511b to your computer and use it in GitHub Desktop.
#include <MemoryLeakDetector.h>
void foo() {
BEGINMEMORYLEAKCHECK();
int * j = new int;
ENDMEMORYLEAKCHECK();/*Leak 2 of 4 bytes detected.*/
}
int main(void) {
/*Because we use a global stack we can nest our macro use!*/
BEGINMEMORYLEAKCHECK();
BEGINMEMORYLEAKCHECK();
int * i = new int;
ENDMEMORYLEAKCHECK();/*Leak 1 of 4 bytes detected.*/
delete i;/*Leak 1 is closed.*/
foo();/*but we generate a leak 2 of 4 bytes inside of foo*/
ENDMEMORYLEAKCHECK();/*Leak 2 of 4 bytes is detected here as well*/
}
#include <MemoryLeakDetector.h>
void foo() {
BEGINMEMORYLEAKCHECK();
int * j = new int;
ENDMEMORYLEAKCHECK();/*Leak 2 of 4 bytes detected.*/
}
int main(void) {
/*Because we use a global stack we can nest our macro use!*/
BEGINMEMORYLEAKCHECK();
BEGINMEMORYLEAKCHECK();
int * i = new int;
ENDMEMORYLEAKCHECK();/*Leak 1 of 4 bytes detected.*/
delete i;/*Leak 1 is closed.*/
foo();/*but we generate a leak 2 of 4 bytes inside of foo*/
ENDMEMORYLEAKCHECK();/*Leak 2 of 4 bytes is detected here as well*/
}
With the following `MemoryLeakDetector.h` which uses a `std::stack` of `std::unique_ptr<MemoryLeakDetector>` to properly handle the different stack contexts. This allows for nested use of our macros. We use `std::unique_ptr` to not only avoid leaks in our `MemoryLeakDetector` code but also to allow us to utilize `std::move` instead of copying the objects.
#pragma once
#ifdef _DEBUG
//#include <vld.h> /* Visual Leak Detector Memory Leak Detection*/
#include <crtdbg.h> /*VS Memory Leak Detection*/
#include <stack>
#include <memory>
#include <sstream>
#include "Windows.h"
class MemoryLeakDetector {
public:
MemoryLeakDetector() {};
_CrtMemState MEMORYLEAKSTATISTICS1;
_CrtMemState MEMORYLEAKSTATISTICS2;
_CrtMemState MEMORYLEAKSTATISTICS3;
static std::stack<std::unique_ptr<MemoryLeakDetector>>& stack() {
static std::stack<std::unique_ptr<MemoryLeakDetector>> s;
return s;
}
};
#define DBOUT( s ) \
do{ \
std::ostringstream os; \
os << s; \
OutputDebugString(os.str().c_str() ); \
}while(0)
#define BEGINMEMORYLEAKCHECK() do{std::unique_ptr<MemoryLeakDetector> ___memoryleakdetector___ = std::make_unique<MemoryLeakDetector>();\
MemoryLeakDetector::stack().push(std::move(___memoryleakdetector___));\
_CrtMemCheckpoint(&MemoryLeakDetector::stack().top().get()->MEMORYLEAKSTATISTICS1);\
}while(0)
#define ENDMEMORYLEAKCHECK() do{if(MemoryLeakDetector::stack().size()==0){DBOUT("\n"<<__FILE__<<"("<<__LINE__<<"):"<<"<"<<__FUNCTION__<<" ENDMEMORYLEAKCHECK without BEGINMEMORYLEAKCHECK detected\n");\
break;}\
std::unique_ptr<MemoryLeakDetector> ___memoryleakdetector___ = std::move(MemoryLeakDetector::stack().top());MemoryLeakDetector::stack().pop();\
_CrtMemCheckpoint(&___memoryleakdetector___->MEMORYLEAKSTATISTICS2);\
if (_CrtMemDifference(&___memoryleakdetector___->MEMORYLEAKSTATISTICS3, &___memoryleakdetector___->MEMORYLEAKSTATISTICS1, &___memoryleakdetector___->MEMORYLEAKSTATISTICS2)){\
DBOUT("\n"<<__FILE__<<"("<<__LINE__<<"):"<<"<"<<__FUNCTION__<<"> MLD detected a leak\n");\
_CrtMemDumpStatistics(&___memoryleakdetector___->MEMORYLEAKSTATISTICS3);\
DBOUT("\n\n");\
std::cerr << "MLD Leak detected "<<__FILE__<<"("<<__LINE__<<")"<< std::endl;\
}}while(0)
#else
#define BEGINMEMORYLEAKCHECK() do{}while(0)
#define ENDMEMORYLEAKCHECK() do{}while(0)
#define DBOUT( s ) do{}while(0)
#endif
[1]: https://en.wikipedia.org/wiki/Comment_(computer_programming)#Debugging
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment