0

I would like the count the number of malloc calls in a large C++ project.

  • I tried malloc hooks but learned that they were removed.
  • Valgrind Massif tells me how much memory is allocated but I not the number of calls to malloc. Or is there a way to get this data?
  • I could preload a library which replaces malloc. But I could not really find a tutorial on how to do this exactly.

Any quick and easy approach to counting the number of malloc calls would be appreciated!

Andreas Pasternak
  • 1,250
  • 10
  • 18
  • C++ projects don't necessarily use `malloc()` at all, and relatively rarely (unless the code is actually C being compiled as C++) use it directly. You might want to look into ways to override the set of `operator new()` and `operator delete()` functions - these functions dynamically allocate/release raw memory in `new`/`delete` expressions and don't (necessarily) call `malloc()` and related functions since they are not required to. If you're specifically interested in memory usage by standard containers, possibly provide a custom allocator. – Peter Jun 07 '22 at 01:44
  • @Peter Are you sure that C++ doesn't use `malloc` (under the hood)? It mixes with glibc, so while C++ projects should use `new/delete` directly, they [more or less] have to call `malloc/free` underneath. Otherwise, mixing in C code (in some library) would have fragmentation issues (and use of `brk/sbrk` would probably break) if C++ had its own `malloc` replacement. – Craig Estey Jun 07 '22 at 01:52
  • @CraigEstey As I said, there is no requirement in the standard that C++ use `malloc()` "under the hood". Particular implementations are *permitted* (or, more accurately, not disallowed) to use `malloc()`, but there is no guarantee they will - or, if they do, that they will document that fact. The C and C++ standards also say nothing about fragmentation - they simply specify what happens if operations or calls of functions succeed or fail. – Peter Jun 07 '22 at 01:59
  • 1
    You could create a `.so` of your own (loaded via `LD_PRELOAD`) that, using `dlopen/dlsym` intercepts all [glibc] `malloc/free` calls and keeps track of the allocations. See: https://stackoverflow.com/questions/6083337/overriding-malloc-using-the-ld-preload-mechanism – Craig Estey Jun 07 '22 at 02:02
  • @Peter OP is using linux (i.e. `glibc`), so theoretical impl are a bit moot. If C++ had an internal `malloc` replacement, and linked to `glibc` at all, it _would_ break because it would call `brk/sbrk` and so would glibc `malloc`. Since they would not know about each other, glibc could _shrink_ the area and that would unmap what the C++ allocator thinks is still mapped. Thus, the C++ impl for linux/glibc _will_ call glibc `malloc`. Also, it needs to do this because it needs to be able to link to and utilize `.so` written in pure C (that use `malloc`). – Craig Estey Jun 07 '22 at 02:16
  • Just a reminder: number of memory allocations do not need to be equal to the number of memory releases; sometimes `numOfAlloc` can be less than `numOfRelease`. In a clean & memory leak free code, there should be at least 1, but sometimes more than 1 `free` for each `malloc` or `calloc`. Similarly, there should be at least 1, but sometimes more than 1 `delete` for each `new` (depending on the branches of the algorithm tree). – ssd Jun 07 '22 at 02:18
  • 1
    @ssd Not true. Releasing any dynamically allocated memory more than once (not involving null pointers and also correctly counting any sequences of release, reallocate, and release again (e.g. `malloc()` - `realloc()` - `free()`) gives undefined behaviour – Peter Jun 07 '22 at 02:50
  • 1
    @CraigEstey You don't need to use `malloc()`, `brk()` nor `sbrk()` to get memory on unix systems. You can use `mmap()` instead and most libc's do that for large blocks of memory because it actually allows returning memory to the kernel consistently. And use of `mmap()` in one library does not conflict with another library. – Goswin von Brederlow Jun 07 '22 at 03:36
  • @Peter : I didn't mean releasing the same memory allocation more than once. Consider a `char**` array that allocates string pointers and then allocates `char*` arrays. I've seen several code examples that (case 1) release the `char**` pointers as soon as if one of the `char*` malloc fails; this is the first & abnormal end release (algorithm branch 1). (case 2) The second release corresponding to this same memory allocation probably sits on the path to the normal program termination (algorithm branch 2). – ssd Jun 07 '22 at 12:29

0 Answers0