Track C++ Memory Allocations

How to keep track of the memory usage in C?

Try tcmalloc: you are looking for a heap profiler, although valgrind might be more useful initially.

tracking dynamic memory allocation in c/c++

Create wrapper function for malloc(), calloc and free(). In malloc/calloc allocate extra word size to maintain how much memory is to allocate and also sum up the bytes allocated in mc. when doing free, read first header bytes to know how much memory is to be freed and decrease the same size from mc.

How to track memory allocations in C++ (especially new/delete)

I would recommend you to use valgrind for linux. It will catch not freed memory, among other bugs like writing to unallocated memory. Another option is mudflap, which tells you about not freed memory too. Use -fmudflap -lmudflap options with gcc, then start your program with MUDFLAP_OPTIONS=-print-leaks ./my_program.

Here's some very simple code. It's not suitable for sophisticated tracking, but intended to show you how you would do it in principle, if you were to implement it yourself. Something like this (left out stuff calling the registered new_handler and other details).

template<typename T>
struct track_alloc : std::allocator<T> {
typedef typename std::allocator<T>::pointer pointer;
typedef typename std::allocator<T>::size_type size_type;

template<typename U>
struct rebind {
typedef track_alloc<U> other;
};

track_alloc() {}

template<typename U>
track_alloc(track_alloc<U> const& u)
:std::allocator<T>(u) {}

pointer allocate(size_type size,
std::allocator<void>::const_pointer = 0) {
void * p = std::malloc(size * sizeof(T));
if(p == 0) {
throw std::bad_alloc();
}
return static_cast<pointer>(p);
}

void deallocate(pointer p, size_type) {
std::free(p);
}
};

typedef std::map< void*, std::size_t, std::less<void*>,
track_alloc< std::pair<void* const, std::size_t> > > track_type;

struct track_printer {
track_type * track;
track_printer(track_type * track):track(track) {}
~track_printer() {
track_type::const_iterator it = track->begin();
while(it != track->end()) {
std::cerr << "TRACK: leaked at " << it->first << ", "
<< it->second << " bytes\n";
++it;
}
}
};

track_type * get_map() {
// don't use normal new to avoid infinite recursion.
static track_type * track = new (std::malloc(sizeof *track))
track_type;
static track_printer printer(track);
return track;
}

void * operator new(std::size_t size) throw(std::bad_alloc) {
// we are required to return non-null
void * mem = std::malloc(size == 0 ? 1 : size);
if(mem == 0) {
throw std::bad_alloc();
}
(*get_map())[mem] = size;
return mem;
}

void operator delete(void * mem) throw() {
if(get_map()->erase(mem) == 0) {
// this indicates a serious bug
std::cerr << "bug: memory at "
<< mem << " wasn't allocated by us\n";
}
std::free(mem);
}

int main() {
std::string *s = new std::string;
// will print something like: TRACK: leaked at 0x9564008, 4 bytes
}

We have to use our own allocator for our map, because the standard one will use our overridden operator new, which would result in an infinite recursion.

Make sure if you override operator new, you use the map to register your allocations. Deleting memory allocated by placement forms of new will use that delete operator too, so it can become tricky if some code you don't know has overloaded operator new not using your map, because operator delete will tell you that it wasn't allocated and use std::free to free the memory.

Also note, as Pax pointed out for his solution too, this will only show leaks that are caused by code using our own defined operator new/delete. So if you want to use them, put their declaration in a header, and include it in all files that should be watched.

Does c keep track of allocated heap memory?

The C standard description of free says the following:


  1. The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

Since you changed the pointer, it does not match a pointer returned by a memory management function (i.e. m/re/calloc), the behaviour is undefined, and anything can happen. Including the runtime library noticing that you've tried to free an invalid pointer, but the runtime is not required to do that either.


As for

  1. Does C keep track of memory's allocated on the heap

It might... but it does not necessarily have to...


  1. If not, how does it know what to free and what to not?

Well, if it does free the memory pointed to by a pointer, then it obviously need to have some kind of bookkeeping about the sizes of the allocations... but it does not need to be able to figure out if any pointers are still pointing to that memory area.


  1. And if it has such a knowledge, why doesn't c automatically deallocate such memories just before exiting. why memory leaks?

Usually memory is freed after the process exits by the operating system. That's not the problem. The real problem are the leaks that happen while the program is still running.

how can you track memory allocation in c++

I think this article provides some insights on how it can be done

Memory Allocation Tracking in C -- Am I doing this right?

You have a bug, that could cause a segmentation fault. realloc() could return the same pointer as it is given, in which case you would have added it twice to the array. When you call your free function, it would try and free the same pointer twice, resulting in a segmentation fault error.

Additionally, I don't understand why you have the reset parameter. Why not simply set references and size to 0 in the OM_DESTROY case? It is good practice to always set a pointer to NULL immediately after freeing it.



Related Topics



Leave a reply



Submit