nlib
heap/replace_malloc/replace_malloc.cpp

This sample replaces functions like nlib_malloc and nlib_free with implementations using nmalloc and nfree. It replaces new and delete

This samples operations can be accomplished more easily by defining the macro NLIB_REPLACE_MALLOC_NEW in NMalloc.h.

#include <new>
#include <vector>
#include "nn/nlib/Config.h"
#if 1
// They must be C Linkage!
extern "C" {
// In Cygwin, you cannot override the implementation
// because nlib_malloc is not weak symbol.
void* nlib_malloc(size_t n) {
// nlib_printf("calling nmalloc %" PRIuS "\n", n);
return nmalloc(n);
}
void nlib_free(void* p) {
// nlib_printf("calling nfree %p\n", p);
nfree(p);
}
void* nlib_calloc(size_t nmemb, size_t size) { return ncalloc(nmemb, size); }
void* nlib_realloc(void* ptr, size_t size) { return nrealloc(ptr, size); }
void* nlib_memalign(size_t alignment, size_t size) {
// The order must be reverse here...
return nmalloc_aligned(size, alignment);
}
void nlib_free_size(void* ptr, size_t size) { nfree_size(ptr, size); }
}
// Overrides new/delete.
#ifndef NN_PLATFORM_CTR
void* operator new(size_t size) { return nlib_malloc(size); }
void operator delete(void* ptr) NLIB_NOEXCEPT { nlib_free(ptr); }
void* operator new(size_t size, const std::nothrow_t&) NLIB_NOEXCEPT { return nlib_malloc(size); }
void operator delete(void* ptr, const std::nothrow_t&) NLIB_NOEXCEPT { nlib_free(ptr); }
void* operator new[](size_t size) { return nlib_malloc(size); }
void operator delete [](void* ptr) NLIB_NOEXCEPT { nlib_free(ptr); }
void* operator new[](size_t size, const std::nothrow_t&) NLIB_NOEXCEPT { return nlib_malloc(size); }
void operator delete[](void* ptr, const std::nothrow_t&) NLIB_NOEXCEPT { nlib_free(ptr); }
// for C++14 sized deallocation
void
operator delete(void* ptr, size_t size) NLIB_NOEXCEPT {
nlib_free_size(ptr, size);
}
void operator delete(void* ptr, size_t size, const std::nothrow_t&) NLIB_NOEXCEPT {
nlib_free_size(ptr, size);
}
void operator delete[](void* ptr, size_t size) NLIB_NOEXCEPT { nlib_free_size(ptr, size); }
void operator delete[](void* ptr, size_t size, const std::nothrow_t&) NLIB_NOEXCEPT {
nlib_free_size(ptr, size);
}
#else
void* operator new(size_t size) throw(std::bad_alloc) { return nlib_malloc(size); }
void operator delete(void* ptr) throw() { nlib_free(ptr); }
void* operator new(size_t size, const std::nothrow_t&) throw() { return nlib_malloc(size); }
void* operator new[](size_t size) throw(std::bad_alloc) { return nlib_malloc(size); }
void operator delete[](void* ptr) throw() { nlib_free(ptr); }
void* operator new[](size_t size, const std::nothrow_t&) throw() { return nlib_malloc(size); }
#endif
#else
#endif
// Now std::allocator calls nmalloc/nfree.
typedef std::vector<int> MyVec;
static bool vector_pushback() {
MyVec vec;
for (int i = 0; i < 10000; ++i) {
vec.push_back(i);
if (i == 5000) {
// You can dump the current status of the heap in XML.
nlib_printf("#\n# heap status: i == 5000\n#\n");
// Note that it shows the cached memory allocated.
// You have to return the memory to the central heap,
// or set NMALLOC_HEAPOPTION_CACHE_DISABLE to heap_option.
}
}
// Verifies here
for (int i = 0; i < 10000; ++i) {
if (vec[i] != i) return false;
}
// Dump again.
nlib_printf("#\n# heap status: i == 10000\n#\n");
// vec.clear() and Dumps again.
vec.clear();
nlib_printf("#\n# heap status: vec.clear()\n#\n");
nmalloc_dumpex(NMALLOC_DUMP_ALL); // the vector is free, but memory is not freed.
// vec.clear() does not free the memory for the vector.
MyVec(vec).swap(vec);
nlib_printf("#\n# heap status: fitting\n#\n");
nmalloc_dumpex(NMALLOC_DUMP_ALL); // memory is freed...
return true;
}
static bool vector_pushback_with_reserve() {
MyVec vec;
vec.reserve(10000);
for (int i = 0; i < 10000; ++i) {
vec.push_back(i);
}
// Verifies here
for (int i = 0; i < 10000; ++i) {
if (vec[i] != i) return false;
}
nlib_printf("#\n# heap status: i == 10000(with reserve)\n#\n");
nmalloc_dumpex(NMALLOC_DUMP_ALL); // fragmentation could be avoided.
return true;
}
#ifdef NLIB_HAS_VIRTUALMEMORY
extern "C" void nmalloc_get_settings(NMallocSettings* settings) {
settings->addr = NULL;
settings->size = 1024 * 512;
settings->heap_option = 0;
}
#else
const size_t heapmem_size = 1024 * 512;
NLIB_ALIGNAS(4096) static char heapmem[heapmem_size];
extern "C" void nmalloc_get_settings(NMallocSettings* settings) {
settings->addr = heapmem;
settings->size = heapmem_size;
settings->heap_option = 0;
}
#endif
static bool SampleMain(int, char**) {
return vector_pushback() && vector_pushback_with_reserve();
}
NLIB_MAINFUNC