0

I'm trying to visualize when C++ STL data structures allocate/deallocate memory. I wrote some code to define custom malloc, calloc, realloc, new.

When I use these custom function or new in my code it is called successfully. But what I want to do is make C++ STL(list, vector, map...) call my custom functions when memory allocation/deallocation. Are there additional things to make C++ STL call my custom functions?

These are my code. I designed to work when memory.h included.

/* memory.h */
#ifndef MEMORY_MEMORY_H_
#define MEMORY_MEMORY_H_

#include "memoryfunc.h"

#undef malloc
#define malloc(SIZE) my_malloc((SIZE), __FILE__, __LINE__)
#undef free
#define free(PTR) my_free((PTR), __FILE__, __LINE__)
#undef calloc
#define calloc(NMEMB, SIZE) my_calloc((NMEMB), (SIZE), __FILE__, __LINE__)
#undef realloc
#define realloc(PTR, SIZE) my_realloc((PTR), (SIZE), __FILE__, __LINE__)

#ifdef __cplusplus

#undef my_new
#define my_new new(__FILE__, __LINE__)
#undef new
#define new my_new

#endif // __cplusplus

#endif // MEMORY_MEMORY_H_
/* memoryfunc.h */
#ifndef MEMORY_MEMORYFUNC_H_
#define MEMORY_MEMORYFUNC_H_

#include <stdio.h>
#include "memoryhook.h"

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

void *my_malloc(size_t size, const char *file, const int line);
void my_free(void *ptr, const char *file, const int line);
void *my_calloc(size_t nmemb, size_t size, const char *file, const int line);
void *my_realloc(void *ptr, size_t size, const char *file, const int line);

#ifdef __cplusplus
}

#include <new>

void *operator new (size_t size, const char *file, const int line);
void *operator new[](size_t size, const char *file, const int line);

#endif // __cplusplus

#endif // MEMORY_MEMORYFUNC_H_
/* memoryfunc.cc */
#include <cstdio>
#include "memoryfunc.h"

void *my_malloc(size_t size, const char *file, const int line) {
    void *res = MemoryHook::instance()._malloc(size);
    fprintf(stdout, "[memory] %zu bytes allocated in %0X using malloc(%d) by %s:%d\n",
            size, res, size, file, line);
    return res;
}

void my_free(void *ptr, const char *file, const int line) {
    MemoryHook::instance()._free(ptr);
    fprintf(stdout, "[memory] free(%0X) by %s:%d\n", ptr, file, line);
}

void *my_calloc(size_t nmemb, size_t size, const char *file, const int line) {
    void *res = MemoryHook::instance()._calloc(nmemb, size);
    fprintf(stdout, "[memory] %zu bytes allocated in %0X using malloc(%zu, %zu) by %s:%d:\n",
        nmemb * size, res, nmemb, size, file, line);
    return res;
}

void *my_realloc(void *ptr, size_t size, const char *file, const int line) {
    void *res = MemoryHook::instance()._realloc(ptr, size);
    fprintf(stdout, "[memory] %zu bytes allocated in %0X using realloc(%0X, %zu) by %s:%d\n",
            size, res, ptr, size, file, line);
    return res;
}

#ifdef __cplusplus

void *operator new (size_t size, const char *file, const int line) {
    void *res = MemoryHook::instance()._malloc(size);
    fprintf(stdout, "[memory] %zu bytes allocated in %0x using new by %s:%d\n", size, res, file, line);
    return res;
}

void *operator new[](size_t size, const char *file, const int line) {
    void *res = MemoryHook::instance()._malloc(size);
    fprintf(stdout, "[memory] %zu bytes allocated in %0x using new[] by %s:%d\n", size, res, file, line);
    return res;
}

void operator delete(void *ptr, const char *file, const int line) {
  MemoryHook::instance()._free(ptr);
  fprintf(stdout, "[memory] delete %0X by %s:%d\n", ptr, file, line);
}

void operator delete[](void *ptr, const char *file, const int line) {
  MemoryHook::instance()._free(ptr);
  fprintf(stdout, "[memory] delete %0X by %s:%d\n", ptr, file, line);
}

#endif // __cplusplus
/* memoryhook.h */
#ifndef MEMORY_MEMORYHOOK_H
#define MEMORY_MEMORYHOOK_H

#include <cstddef>

class MemoryHook {
 protected:
  MemoryHook();
  virtual ~MemoryHook();

 public:
  typedef void *(*MallocFunc) (size_t size);
  typedef void  (*FreeFunc)   (void  *ptr);
  typedef void *(*CallocFunc) (size_t nmemb, size_t size);
  typedef void *(*ReallocFunc)(void  *ptr,   size_t size);

  MallocFunc  _malloc_orig  = nullptr, _malloc  = nullptr;
  FreeFunc    _free_orig    = nullptr, _free    = nullptr;
  CallocFunc  _calloc_orig  = nullptr, _calloc  = nullptr;
  ReallocFunc _realloc_orig = nullptr, _realloc = nullptr;

 public:
  void hook(
    MallocFunc malloc_func = nullptr,
    FreeFunc   free_func = nullptr,
    CallocFunc calloc_func = nullptr,
    ReallocFunc realloc_func = nullptr);
  void unhook();

 public:
  static MemoryHook &instance();
};

#endif // MEMORY_MEMORYHOOK_H
/* memoryhook.cc */
#include <cstdio>
#include <cstdlib>
#include <dlfcn.h>
#include "memoryhook.h"

MemoryHook::MemoryHook() {
  printf("MemoryHook()\n");
  _malloc_orig = _malloc = reinterpret_cast<MallocFunc>(dlsym(RTLD_NEXT, "malloc"));
  if (_malloc_orig == nullptr) {
    fprintf(stderr, "[mem] dlsym(\"malloc\") returned nullptr. dlerror = %s\n", dlerror());
    goto _fail;
  }
  _free_orig = _free = reinterpret_cast<FreeFunc>(dlsym(RTLD_NEXT, "free"));
  if (_free_orig == nullptr) {
    fprintf(stderr, "[mem] dlsym(\"free\") returned nullptr. dlerror = %s\n", dlerror());
    goto _fail;
  }
  _calloc_orig = _calloc = reinterpret_cast<CallocFunc>(dlsym(RTLD_NEXT, "calloc"));
  if (_calloc_orig == nullptr) {
    fprintf(stderr, "[mem] dlsym(\"calloc\") returned nullptr. dlerror = %s\n", dlerror());
    goto _fail;
  }
  _realloc_orig = _realloc = reinterpret_cast<ReallocFunc>(dlsym(RTLD_NEXT, "realloc"));
  if (_realloc_orig == nullptr) {
    fprintf(stderr, "[mem] dlsym(\"realloc\") returned nullptr. dlerror = %s\n", dlerror());
    goto _fail;
  }
  return;
 _fail:
  abort();
}

MemoryHook::~MemoryHook() {
}

void MemoryHook::hook(
    MallocFunc malloc_func,
    FreeFunc free_func,
    CallocFunc calloc_func,
    ReallocFunc realloc_func) {
  if (malloc_func != nullptr) _malloc = malloc_func;
  if (free_func != nullptr) _free = free_func;
  if (calloc_func != nullptr) _calloc = calloc_func;
  if (realloc_func != nullptr) _realloc = realloc_func;
}

void MemoryHook::unhook() {
  _malloc  = _malloc_orig;
  _free    = _free_orig;
  _calloc  = _calloc_orig;
  _realloc = _realloc_orig;
}

MemoryHook &MemoryHook::instance() {
  static MemoryHook instance_;
  return instance_;
}

#ifdef MEMORY_GLOBAL_HOOK

void *malloc(size) {
  return MemoryHook::instance().malloc_(size);
}

void free(void *ptr) {
  MemoryHook::instance().free_(ptr);
}

void *calloc(size_t nmemb, size_t size) {
  return MemoryHook::instance().calloc_(nmemb, size);
}

void *realloc(void *ptr, sizee_t size) {
  return MemoryHook::instance().realloc_(ptr, size);
}

#endif // MEMORY_GLOBAL_HOOK
  • Possibly related: https://stackoverflow.com/questions/826569/compelling-examples-of-custom-c-allocators – Eljay Jul 26 '20 at 12:16
  • I think std::allocator is what I've been found. I will try links Eljay and Sprite commented. Thanks –  Jul 26 '20 at 12:23

0 Answers0