// memory.cpp
#include "memchk.h"
// finding memory leak
int main()
{
        int* p1 = new int;
        int* p2 = new int;
        int* p3 = new int;
        delete p2;
//      cout << __FILE__ << endl;     // 컴파일 하는 파일이름
//      cout << __LINE__ << endl;     // 컴파일 하는 LINE NO
        return 0;
}
//memchk.h
#include <iostream>
using std::cout;
using std::endl;       // .h 에서는 절대로 namespace를 통째로 열지마라!!(격언중하나)
#ifdef _DEBUG
struct MemInfo
{
        char name[256];        // 화일이름
        int  line;             // new를호출한line no
        void* addr;            // 할당한메모리주소
};
MemInfo mem[10000];  // 최대10000개의 메모리 할당을기록( linked list를 사용해도 됨 )
int count = 0;
void* operator new( size_t s, char* file, int line )
{
        void* p = malloc( s );
        // 배열에 할당정보를 기록한다.
        mem[count].addr = p;
        mem[count].line = line;
        strcpy( mem[count].name, file );
        ++count;
        return p;
}
void operator delete( void* p )
{
        for( int i = 0; i < count; i++ )
        {
               if( mem[i].addr == p )
               {
                       mem[i] = mem[count-1]; // i번째를 제거
                       --count;
                       break;
               }
        }
        // 배열에 없는 정보라면 에러처리를 하는 것도 좋은방법.
        free(p);
}
int MAIN();
void main()
{
        MAIN();
        if ( count == 0 )
        {
               cout << "NO Memory Leak" << endl;
               return;
        }
        cout << "Found " << count << " Memory Leak" << endl;
        for( int i = 0; i < count; ++i )
        {
               cout << "FILE : " << mem[i].name << endl;
               cout << "FILE : " << mem[i].addr << endl;
               cout << "FILE : " << mem[i].line << endl;
               cout << endl;
        }
}
// 꼭 외워 두세요. new에 인자를 더 보내주기 위한 좋은 방법
#define new new(__FILE__, __LINE__)
#define main MAIN
// C에 적용해보고 싶을때!!
#define malloc(x)      MyMAlloc( x, __FILE__, __LINE__ )
#define free(x)               MyFree(x)
#endif // _DEBUG
