Created
March 8, 2016 09:35
-
-
Save anonymous/f41657c289a2547f511b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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*/ | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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