Compare commits

...

4 commits

Author SHA1 Message Date
14301c372d Update Changelog.md, version 2.8 2024-11-12 16:33:16 +09:00
293b18e4bf Avoid segfault on exit(...)
Avoids segfault by not freeing the internal structure handling memory
allocations. When the process ends, the OS should reclaim all memory,
even if it isn't free'd during process execution.
2024-11-12 16:32:23 +09:00
33d3adba3f Cleanup of Stats struct 2024-11-12 16:10:10 +09:00
4d3d6c9168 Use atexit() instead of onexit() 2024-11-12 15:29:17 +09:00
4 changed files with 38 additions and 16 deletions

View file

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.7) cmake_minimum_required(VERSION 3.7)
project(AnotherMemCheck) project(AnotherMemCheck)
set(AnotherMemCheck_VERSION 2.7) set(AnotherMemCheck_VERSION 2.8)
set(AnotherMemCheck_SOVERSION 2) set(AnotherMemCheck_SOVERSION 2)
set(AnotherMemCheck_SOURCES set(AnotherMemCheck_SOURCES

View file

@ -1,5 +1,11 @@
# Changelog # Changelog
## Version 2.8
Internal refactorings.
Minor change to avoid segfault when program exits with `exit(...)` function.
## Version 2.7 ## Version 2.7
Fix incorrect initialization. Fix incorrect initialization.

View file

@ -8,6 +8,9 @@
// Local includes. // Local includes.
#include "another_memcheck.h" #include "another_memcheck.h"
// Function declaration.
void exit_handler_stats();
namespace SC_AM_Internal { namespace SC_AM_Internal {
Stats *stats = nullptr; Stats *stats = nullptr;
int is_env_status = 0; int is_env_status = 0;
@ -16,7 +19,7 @@ namespace SC_AM_Internal {
Stats *get_init_stats() { Stats *get_init_stats() {
Stats *stats = reinterpret_cast<SC_AM_Internal::Stats*>( Stats *stats = reinterpret_cast<SC_AM_Internal::Stats*>(
real_malloc(sizeof(Stats))); real_malloc(sizeof(Stats)));
stats->initialize(); [[maybe_unused]] void *unused = new(stats) Stats{};
is_env_status = getenv("ANOTHER_MEMCHECK_QUIET") != nullptr is_env_status = getenv("ANOTHER_MEMCHECK_QUIET") != nullptr
? ANOTHER_MEMCHECK_QUIET_EXISTS ? ANOTHER_MEMCHECK_QUIET_EXISTS
: ANOTHER_MEMCHECK_QUIET_NOT_EXISTS; : ANOTHER_MEMCHECK_QUIET_NOT_EXISTS;
@ -77,9 +80,6 @@ namespace SC_AM_Internal {
} }
Stats::Stats() : malloced_list_head(nullptr), malloced_list_tail(nullptr), deferred_node(nullptr), recursive_mutex(nullptr) { Stats::Stats() : malloced_list_head(nullptr), malloced_list_tail(nullptr), deferred_node(nullptr), recursive_mutex(nullptr) {
}
void Stats::initialize() {
malloced_list_head = reinterpret_cast<ListNode*>(real_malloc(sizeof(ListNode))); malloced_list_head = reinterpret_cast<ListNode*>(real_malloc(sizeof(ListNode)));
malloced_list_tail = reinterpret_cast<ListNode*>(real_malloc(sizeof(ListNode))); malloced_list_tail = reinterpret_cast<ListNode*>(real_malloc(sizeof(ListNode)));
malloced_list_head->next = malloced_list_tail; malloced_list_head->next = malloced_list_tail;
@ -92,17 +92,12 @@ namespace SC_AM_Internal {
deferred_node = nullptr; deferred_node = nullptr;
recursive_mutex = real_malloc(sizeof(std::recursive_mutex)); recursive_mutex = real_malloc(sizeof(std::recursive_mutex));
void *unused = new(recursive_mutex) std::recursive_mutex{}; [[maybe_unused]] void *unused = new(recursive_mutex) std::recursive_mutex{};
(void)unused;
on_exit([] ([[maybe_unused]] int status, void *ptr) { std::atexit(exit_handler_stats);
Stats *stats = reinterpret_cast<Stats*>(ptr);
stats->print_status();
stats->cleanup();
}, this);
} }
void Stats::cleanup() { Stats::~Stats() {
using std_recursive_mutex = std::recursive_mutex; using std_recursive_mutex = std::recursive_mutex;
((std::recursive_mutex*)recursive_mutex)->~std_recursive_mutex(); ((std::recursive_mutex*)recursive_mutex)->~std_recursive_mutex();
real_free(recursive_mutex); real_free(recursive_mutex);
@ -218,4 +213,17 @@ namespace SC_AM_Internal {
} }
} }
// Function definition.
void exit_handler_stats() {
if (SC_AM_Internal::stats != nullptr) {
SC_AM_Internal::stats->print_status();
// Avoids segfault when program calls `exit(...)`. OS should reclaim memory
// when the process ends even if it isn't free'd here.
//using SCS_AM_INTERNAL_Stats = SC_AM_Internal::Stats;
//SC_AM_Internal::stats->~SCS_AM_INTERNAL_Stats();
//SC_AM_Internal::stats = nullptr;
}
}
// vim: et sw=2 ts=2 sts=2 // vim: et sw=2 ts=2 sts=2

View file

@ -1,6 +1,8 @@
#ifndef SEODISPARATE_COM_ANOTHER_MEMCHECK_H #ifndef SEODISPARATE_COM_ANOTHER_MEMCHECK_H
#define SEODISPARATE_COM_ANOTHER_MEMCHECK_H #define SEODISPARATE_COM_ANOTHER_MEMCHECK_H
#include <cstdint>
namespace SC_AM_Internal { namespace SC_AM_Internal {
// Forward declaration. // Forward declaration.
struct Stats; struct Stats;
@ -48,15 +50,21 @@ namespace SC_AM_Internal {
struct Stats { struct Stats {
Stats(); Stats();
~Stats();
// Disable copy.
Stats(Stats &other) = delete;
Stats& operator=(Stats &other) = delete;
// Disable move.
Stats(Stats &&other) = delete;
Stats& operator=(Stats &&other) = delete;
ListNode *malloced_list_head; ListNode *malloced_list_head;
ListNode *malloced_list_tail; ListNode *malloced_list_tail;
ListNode *deferred_node; ListNode *deferred_node;
void *recursive_mutex; void *recursive_mutex;
void initialize();
void cleanup();
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); void *do_realloc(void*, std::size_t size);