The basic methods most common tools use is replace all functions that directly manipulate memory addresses, i. e. alloc, malloc, calloc, realloc, free, new, delete, and maybe also functions like memset, memmove, etc.. You could do this by replacing all of these functions with macros, but a safer way would be defining a new_handler (see http://www.cplusplus.com/reference/std/new/set_new_handler/
]), but doing so will not affect compiled libs you link to your program or dlls loaded at runtime. The concept is, everytime you allocate memory, you allocate some additional memory to save statistics and data for analysis, either in a separate place, or right in the same memory block. Then, everytime you free memory, you use that additional data to verify the memory block at the given address was indeed allocated and hasn't been freed already.
That said, most compilers implement the existing functions already just like that, at least when you compile them in debug mode. You'll have to check the compiler documentation to find out more. E. g. Visual Studio, if used to run a program in debug mode, will at the normal exit of the program print a list of memory blocks that weren't properly freed, along with the source file locations they were allocated in. (if that information is available)
Also, all modern OSes allocate memory through specialiced memory managers that are capable of emulating a huge chunk of contiguous memory, even if the actual, physical memory currently in use is already fragmented to smaller bits. All memory accesses have to pass through that memory manager in order to determine the physical address, so if you are interested in the actual physical addresses your program uses, it will be a lot harder to determine. This will not be relevant however as long as you don't intend to analyze memory locations of other
programs from a different process.