Skip to content

Instantly share code, notes, and snippets.

@alk
Created June 7, 2024 18:17
Show Gist options
  • Save alk/f73d13f73d47deaca3921cb8d7660bf2 to your computer and use it in GitHub Desktop.
Save alk/f73d13f73d47deaca3921cb8d7660bf2 to your computer and use it in GitHub Desktop.
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// #include "config_for_unittests.h"
#include "gtest/gtest.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <unordered_map>
static __thread bool in_tracker __attribute__ ((tls_model ("initial-exec")));
struct CanTrack {
bool was_in_tracker;
CanTrack() : was_in_tracker(in_tracker) {
if (!was_in_tracker) {
in_tracker = true;
}
}
bool operator()() {
return !was_in_tracker;
}
~CanTrack() {
in_tracker = was_in_tracker;
}
};
static size_t stored_counter;
static std::unordered_map<void*, size_t> sizes;
static struct StartCleanup {
~StartCleanup() {
in_tracker = true;
fprintf(stderr, "total_stored_counter = %zu\nsize.size() = %zu\n", stored_counter, sizes.size());
}
} start_cleanup;
static void store_size(void* ptr, size_t s) {
assert(in_tracker);
bool inserted = sizes.emplace(ptr, s).second;
(void)inserted;
assert(inserted);
stored_counter++;
}
static void check_remove_size(void* ptr, size_t s) {
assert(in_tracker);
auto iter = sizes.find(ptr);
if (iter == sizes.end()) {
fprintf(stderr, "deleting untracked pointer? %p (s = %zu)\n", ptr, s);
asm volatile ("int $3; nop" : : : "memory");
return;
}
if (s != 0 && iter->second != s) {
fprintf(stderr, "tracked size mismatch %p (s = %zu)\n", ptr, s);
asm volatile ("int $3; nop" : : : "memory");
}
sizes.erase(iter);
}
static void* do_allocate(size_t size, size_t alignment = 0) {
void* addr = alignment ? aligned_alloc(alignment, size) : malloc(size);
CanTrack ct;
if (ct()) {
store_size(addr, size);
}
return addr;
}
static void do_free(void* p, size_t sz = 0) {
CanTrack ct;
if (ct() && p != nullptr) {
check_remove_size(p, sz);
}
free(p);
}
void* operator new(size_t size) {
return do_allocate(size);
}
void operator delete(void* p) noexcept {
do_free(p);
}
void* operator new[](size_t size) {
return do_allocate(size);
}
void operator delete[](void* p) noexcept {
do_free(p);
}
void* operator new(size_t size, const std::nothrow_t& nt) noexcept {
return do_allocate(size);
}
void* operator new[](size_t size, const std::nothrow_t& nt) noexcept {
return do_allocate(size);
}
void operator delete(void* ptr, const std::nothrow_t& nt) noexcept {
do_free(ptr);
}
void operator delete[](void* ptr, const std::nothrow_t& nt) noexcept {
do_free(ptr);
}
void operator delete(void* p, size_t s) noexcept {
do_free(p, s);
}
void operator delete[](void* p, size_t s) noexcept {
do_free(p, s);
}
void* operator new(size_t size, std::align_val_t al) {
return do_allocate(size, static_cast<size_t>(al));
}
void operator delete(void* p, std::align_val_t al) noexcept {
do_free(p);
}
void* operator new[](size_t size, std::align_val_t al) {
return do_allocate(size, static_cast<size_t>(al));
}
void operator delete[](void* p, std::align_val_t al) noexcept {
do_free(p);
}
void* operator new(size_t size, std::align_val_t al, const std::nothrow_t& nt) noexcept {
return do_allocate(size, static_cast<size_t>(al));
}
void* operator new[](size_t size, std::align_val_t al, const std::nothrow_t& nt) noexcept {
return do_allocate(size, static_cast<size_t>(al));
}
void operator delete(void* ptr, std::align_val_t al, const std::nothrow_t& nt) noexcept {
do_free(ptr);
}
void operator delete[](void* ptr, std::align_val_t al, const std::nothrow_t& nt) noexcept {
do_free(ptr);
}
TEST(TrivialSizedTest, Basic) {
::operator delete(::operator new(32), 32);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment