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