// Cuenta los bytes reservados con new y todavía sin liberar. Se incluye en un solo .cpp.
#ifndef BYTES_COUNTER_H
#define BYTES_COUNTER_H

#include <cstddef>
#include <cstdlib>
#include <new>

inline std::size_t& live_bytes() {
    static std::size_t bytes = 0;
    return bytes;
}

// Cada bloque guarda su tamaño en un encabezado, para descontarlo al liberar.
namespace bytes_counter {
constexpr std::size_t kHeader = 16;
}

[[gnu::noinline]] void* operator new(std::size_t size) {
    void* raw = std::malloc(size + bytes_counter::kHeader);
    if (raw == nullptr) {
        throw std::bad_alloc();
    }
    *static_cast<std::size_t*>(raw) = size;
    live_bytes() += size;
    return static_cast<char*>(raw) + bytes_counter::kHeader;
}

[[gnu::noinline]] void operator delete(void* block) noexcept {
    if (block != nullptr) {
        char* raw = static_cast<char*>(block) - bytes_counter::kHeader;
        live_bytes() -= *reinterpret_cast<std::size_t*>(raw);
        std::free(raw);
    }
}

[[gnu::noinline]] void operator delete(void* block, std::size_t) noexcept {
    operator delete(block);
}

#endif
