Compare commits
2 commits
23b851d8f3
...
d4c47f871b
Author | SHA1 | Date | |
---|---|---|---|
d4c47f871b | |||
563d6ad570 |
5 changed files with 92 additions and 8 deletions
|
@ -1,7 +1,7 @@
|
||||||
cmake_minimum_required(VERSION 3.7)
|
cmake_minimum_required(VERSION 3.7)
|
||||||
project(AnotherMemCheck)
|
project(AnotherMemCheck)
|
||||||
|
|
||||||
set(AnotherMemCheck_VERSION 2.4)
|
set(AnotherMemCheck_VERSION 2.5)
|
||||||
set(AnotherMemCheck_SOVERSION 2)
|
set(AnotherMemCheck_SOVERSION 2)
|
||||||
|
|
||||||
set(AnotherMemCheck_SOURCES
|
set(AnotherMemCheck_SOURCES
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Version 2.5
|
||||||
|
|
||||||
|
Added support for realloc().
|
||||||
|
|
||||||
## Version 2.4
|
## Version 2.4
|
||||||
|
|
||||||
Fixed free() not actually calling real_free().
|
Fixed free() not actually calling real_free().
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace SC_AM_Internal {
|
||||||
|
|
||||||
void *(*real_malloc)(std::size_t) = nullptr;
|
void *(*real_malloc)(std::size_t) = nullptr;
|
||||||
void *(*real_calloc)(std::size_t, std::size_t) = nullptr;
|
void *(*real_calloc)(std::size_t, std::size_t) = nullptr;
|
||||||
|
void *(*real_realloc)(void*, std::size_t) = nullptr;
|
||||||
void (*real_free)(void*) = nullptr;
|
void (*real_free)(void*) = nullptr;
|
||||||
|
|
||||||
Malloced::Malloced() : address(nullptr), size(0), id(0) {}
|
Malloced::Malloced() : address(nullptr), size(0), id(0) {}
|
||||||
|
@ -39,18 +40,34 @@ namespace SC_AM_Internal {
|
||||||
new_node->data = data;
|
new_node->data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ListNode::remove_from_list(ListNode *head, void *ptr) {
|
void ListNode::add_to_list(ListNode *tail, ListNode *node) {
|
||||||
|
node->next = tail;
|
||||||
|
node->prev = tail->prev;
|
||||||
|
tail->prev->next = node;
|
||||||
|
tail->prev = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ListNode::remove_from_list(ListNode *head,
|
||||||
|
void *ptr,
|
||||||
|
Stats *defer_handler) {
|
||||||
ListNode *node = head;
|
ListNode *node = head;
|
||||||
while (node != nullptr) {
|
while (node != nullptr) {
|
||||||
node = node->next;
|
node = node->next;
|
||||||
if (node && node->data && node->data->address == ptr) {
|
if (node && node->data && node->data->address == ptr) {
|
||||||
if (is_env_status == ANOTHER_MEMCHECK_QUIET_NOT_EXISTS) {
|
if (is_env_status == ANOTHER_MEMCHECK_QUIET_NOT_EXISTS) {
|
||||||
std::clog << " id: " << node->data->id << std::endl;
|
std::clog << " removing id: " << node->data->id;
|
||||||
|
if (!defer_handler) {
|
||||||
|
std::clog << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
node->prev->next = node->next;
|
node->prev->next = node->next;
|
||||||
node->next->prev = node->prev;
|
node->next->prev = node->prev;
|
||||||
|
if (defer_handler) {
|
||||||
|
defer_handler->deferred_node = node;
|
||||||
|
} else {
|
||||||
real_free(node->data);
|
real_free(node->data);
|
||||||
real_free(node);
|
real_free(node);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +75,7 @@ namespace SC_AM_Internal {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stats::Stats() : malloced_list_head(nullptr), malloced_list_tail(nullptr), pthread_mutex{.__align=0} {
|
Stats::Stats() : malloced_list_head(nullptr), malloced_list_tail(nullptr), deferred_node(nullptr), pthread_mutex{.__align=0} {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stats::initialize() {
|
void Stats::initialize() {
|
||||||
|
@ -71,6 +88,8 @@ namespace SC_AM_Internal {
|
||||||
malloced_list_head->data = nullptr;
|
malloced_list_head->data = nullptr;
|
||||||
malloced_list_tail->data = nullptr;
|
malloced_list_tail->data = nullptr;
|
||||||
|
|
||||||
|
deferred_node = nullptr;
|
||||||
|
|
||||||
pthread_mutex_init(&pthread_mutex, nullptr);
|
pthread_mutex_init(&pthread_mutex, nullptr);
|
||||||
|
|
||||||
on_exit([] ([[maybe_unused]] int status, void *ptr) {
|
on_exit([] ([[maybe_unused]] int status, void *ptr) {
|
||||||
|
@ -129,6 +148,45 @@ namespace SC_AM_Internal {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *Stats::do_realloc(void *ptr, std::size_t size) {
|
||||||
|
if(int ret = pthread_mutex_lock(&pthread_mutex); ret == EINVAL) {
|
||||||
|
std::clog << "ERROR: pthread mutex not properly initialized!\n";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr) {
|
||||||
|
if (!ListNode::remove_from_list(malloced_list_head, ptr, this)) {
|
||||||
|
std::clog << "WARNING: Attempted free of unknown memory location!\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *address = real_realloc(ptr, size);
|
||||||
|
if (address != nullptr) {
|
||||||
|
if (deferred_node) {
|
||||||
|
deferred_node->data->address = address;
|
||||||
|
deferred_node->data->size = size;
|
||||||
|
deferred_node->data->id = deferred_node->data->count++;
|
||||||
|
if (is_env_status == ANOTHER_MEMCHECK_QUIET_NOT_EXISTS) {
|
||||||
|
std::clog << ", adding id: " << deferred_node->data->id << std::endl;
|
||||||
|
}
|
||||||
|
ListNode::add_to_list(malloced_list_tail, deferred_node);
|
||||||
|
deferred_node = nullptr;
|
||||||
|
} else {
|
||||||
|
Malloced *data = reinterpret_cast<Malloced*>(real_malloc(sizeof(Malloced)));
|
||||||
|
data->address = address;
|
||||||
|
data->size = size;
|
||||||
|
data->id = data->count++;
|
||||||
|
if (is_env_status == ANOTHER_MEMCHECK_QUIET_NOT_EXISTS) {
|
||||||
|
std::clog << ", adding id: " << data->id << std::endl;
|
||||||
|
}
|
||||||
|
ListNode::add_to_list(malloced_list_tail, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&pthread_mutex);
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
bool Stats::do_free(void *ptr) {
|
bool Stats::do_free(void *ptr) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if(int ret = pthread_mutex_lock(&pthread_mutex); ret == EINVAL) {
|
if(int ret = pthread_mutex_lock(&pthread_mutex); ret == EINVAL) {
|
||||||
|
@ -137,7 +195,7 @@ namespace SC_AM_Internal {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptr) {
|
if (ptr) {
|
||||||
if(!ListNode::remove_from_list(malloced_list_head, ptr)) {
|
if (!ListNode::remove_from_list(malloced_list_head, ptr)) {
|
||||||
std::clog << "WARNING: Attempted free of unknown memory location!\n";
|
std::clog << "WARNING: Attempted free of unknown memory location!\n";
|
||||||
} else {
|
} else {
|
||||||
result = true;
|
result = true;
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace SC_AM_Internal {
|
||||||
|
|
||||||
extern void *(*real_malloc)(std::size_t size);
|
extern void *(*real_malloc)(std::size_t size);
|
||||||
extern void *(*real_calloc)(std::size_t n, std::size_t size);
|
extern void *(*real_calloc)(std::size_t n, std::size_t size);
|
||||||
|
extern void *(*real_realloc)(void *ptr, std::size_t size);
|
||||||
extern void (*real_free)(void *ptr);
|
extern void (*real_free)(void *ptr);
|
||||||
|
|
||||||
struct Malloced {
|
struct Malloced {
|
||||||
|
@ -37,8 +38,11 @@ namespace SC_AM_Internal {
|
||||||
ListNode() : next(nullptr), prev(nullptr), data(nullptr) {}
|
ListNode() : next(nullptr), prev(nullptr), data(nullptr) {}
|
||||||
|
|
||||||
static void add_to_list(ListNode *tail, Malloced *data);
|
static void add_to_list(ListNode *tail, Malloced *data);
|
||||||
|
static void add_to_list(ListNode *tail, ListNode *node);
|
||||||
/// Returns true if removed.
|
/// Returns true if removed.
|
||||||
static bool remove_from_list(ListNode *head, void *ptr);
|
static bool remove_from_list(ListNode *head,
|
||||||
|
void *ptr,
|
||||||
|
Stats *defer_handler = nullptr);
|
||||||
|
|
||||||
ListNode *next;
|
ListNode *next;
|
||||||
ListNode *prev;
|
ListNode *prev;
|
||||||
|
@ -51,6 +55,7 @@ namespace SC_AM_Internal {
|
||||||
|
|
||||||
ListNode *malloced_list_head;
|
ListNode *malloced_list_head;
|
||||||
ListNode *malloced_list_tail;
|
ListNode *malloced_list_tail;
|
||||||
|
ListNode *deferred_node;
|
||||||
pthread_mutex_t pthread_mutex;
|
pthread_mutex_t pthread_mutex;
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
|
@ -58,6 +63,7 @@ namespace SC_AM_Internal {
|
||||||
|
|
||||||
void *do_malloc(std::size_t size);
|
void *do_malloc(std::size_t size);
|
||||||
void *do_calloc(std::size_t n, std::size_t size);
|
void *do_calloc(std::size_t n, std::size_t size);
|
||||||
|
void *do_realloc(void*, std::size_t size);
|
||||||
/// true on success.
|
/// true on success.
|
||||||
bool do_free(void *ptr);
|
bool do_free(void *ptr);
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,22 @@ extern "C" {
|
||||||
return SC_AM_Internal::stats->do_calloc(n, size);
|
return SC_AM_Internal::stats->do_calloc(n, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *realloc(void *ptr, std::size_t size) {
|
||||||
|
if (SC_AM_Internal::real_realloc == nullptr) {
|
||||||
|
SC_AM_Internal::real_realloc = reinterpret_cast<void*(*)(void*, std::size_t)>(dlsym(RTLD_NEXT, "realloc"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SC_AM_Internal::stats == nullptr) {
|
||||||
|
SC_AM_Internal::stats = SC_AM_Internal::get_init_stats();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SC_AM_Internal::is_env_status == SC_AM_Internal::ANOTHER_MEMCHECK_QUIET_NOT_EXISTS) {
|
||||||
|
std::clog << "attempting to realloc size: " << size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SC_AM_Internal::stats->do_realloc(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
void free(void *ptr) {
|
void free(void *ptr) {
|
||||||
if (SC_AM_Internal::real_free == nullptr) {
|
if (SC_AM_Internal::real_free == nullptr) {
|
||||||
SC_AM_Internal::real_free = reinterpret_cast<void(*)(void*)>(dlsym(RTLD_NEXT, "free"));
|
SC_AM_Internal::real_free = reinterpret_cast<void(*)(void*)>(dlsym(RTLD_NEXT, "free"));
|
||||||
|
|
Loading…
Reference in a new issue