Leak detection simple class
Here are some things that may help you improve your code.

Use the required #includes

The code uses std::string which means that it should #include &lt;string&gt;.  It might compile on your machine because some other header includes that file, but you can't count on that, and it could change with the next compiler update.

Use only necessary #includes

The #include &lt;stdexcept&gt; and #include &lt;memory&gt; lines are not necessary and can be safely removed because nothing from those headers appears to be used here.

Avoid C-style macros

I'd advise not using C-style macros like the ones in this code, preferring either inline functions or even lambdas.  See ES.31 for details.

Consider thread safety

If multiple threads are using this code, there is likely to be a problem because the single shared instance of the std::vector is not protected by a mutex.  I would also recommend renaming the existing locked variable to something like complete or finished to better distinguish what it's doing.

Avoid singletons

A singleton is basically just another way to create global variables, and we don't like global variables much because they make code linkages much harder to see and understand.  See I.3 for more on that. In this case, since you already have two global variables, much of the complexity can easily be avoided by simply using a namespace instead of a class.  Here's one way to do that which eliminates the need for instance and CREATE_LEAK_DET:

namespace LeakDbg
{
    struct Pair
    {
        std::string name;
        void* ref;
        bool operator==( const Pair &amp;other ) const { return ref == other.ref; }

    };
    static bool locked = false;
    static std::vector&lt;Pair&gt; stack;

    static void addRef(const std::string&amp; nm, void* ptr)
    {
        stack.emplace_back(Pair{ nm, ptr });
    }
    static void remRef(void* ptr)
    {
        if( !LeakDbg::locked ){
            stack.erase(std::remove(stack.begin(), stack.end(), Pair{"",ptr}), stack.end());
        }
    }
    void checkLeakStack()
    {
        std::cout &lt;&lt; "There are " &lt;&lt; LeakDbg::stack.size() &lt;&lt; " leaks ..." "\n";
        for ( LeakDbg::Pair pair : LeakDbg::stack) {
            std::cout &lt;&lt; pair.name &lt;&lt; " is leaked\n";
        }
    }
    static const bool registered{std::atexit( checkLeakStack ) == 0};
}


Consider the user

The current code requires that the user explicitly instruments the code, which seems a bit intrusive.  Here's an alternative approach the modifies things just slightly, using the Curiously Recurring Template Pattern, or CRTP for short.  First we isolate the leak detector bits into a templated class.

template &lt;typename T&gt;
struct LeakDetector {
    LeakDetector() {
        LeakDbg::addRef(typeid(T).name(), this);
    }
    ~LeakDetector() {
        LeakDbg::remRef(this);
    }
};


Now to use it is much simpler than before.  No ugly macros are required and we only need to add one simple thing to the declaration of the class to be monitored:

struct Test : public LeakDetector&lt;Test&gt; 
{
    Test() {
    }
    ~Test() {
    }
};


An even less intrusive approach might be to override new and delete as outlined in this question.

Consider alternatives

Leak detection is a worthwhile thing to do, since many C++ bugs stem from that kind of error.  However, there are already a number of existing approaches to this, some of which may already be installed on your computer.  There is, for example the useful valgrind tool.  If you're using clang or gcc and have the libasan library installed, you can get a very nice runtime printout.  Just compile the code with

g++ -g -fsanitize=address myprogram.cpp -o myprogram


Then at runtime, a memory leak report might look like this:

There are 2 leaks ...
Cls is leaked
Cls is leaked

=================================================================
==71254==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 1 byte(s) in 1 object(s) allocated from:
    #0 0x7fe67c2c69d7 in operator new(unsigned long) (/lib64/libasan.so.5+0x10f9d7)
    #1 0x4057a6 in main /home/edward/test/memleak/src/main.cpp:97
    #2 0x7fe67bcbb1a2 in __libc_start_main (/lib64/libc.so.6+0x271a2)

Direct leak of 1 byte(s) in 1 object(s) allocated from:
    #0 0x7fe67c2c69d7 in operator new(unsigned long) (/lib64/libasan.so.5+0x10f9d7)
    #1 0x405774 in main /home/edward/test/memleak/src/main.cpp:95
    #2 0x7fe67bcbb1a2 in __libc_start_main (/lib64/libc.so.6+0x271a2)

SUMMARY: AddressSanitizer: 2 byte(s) leaked in 2 allocation(s).