替换全局运算符 new / delete 并在其中分配内存,导致堆损坏

Replacing global operator new / delete and allocating memory within these, leading to heap corruption

#include <cstdlib>
#include <memory>
#include <unordered_map>

template <class T>
struct allocator {
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;
  typedef T* pointer;
  typedef const T* const_pointer;
  typedef T& reference;
  typedef const T& const_reference;
  typedef T value_type;

  allocator() = default;

  template <class U>
  allocator(const allocator<U>&) {}

  T* allocate(std::size_t n) const { return (T*)malloc(n); } // debugger breaks here
  void deallocate(T* p, std::size_t) const { free(p); }
};

using allocations_map =
    std::unordered_map<void*, std::size_t, std::hash<void*>,
                       std::equal_to<void*>,
                       allocator<std::pair<void* const, std::size_t>>>;

allocations_map allocations; // heap corruption in the constructor

void* operator new(std::size_t n) {
  auto p = malloc(n);
  allocations.emplace(p, n);
  return p;
}

void operator delete(void* p) noexcept {
  allocations.erase(p);
  free(p);
}

int main() { std::vector<int> v(5); }

为什么我在 allocations_map 的构造函数中破坏了堆?调试器在构造函数内部调用的自定义分配器的 malloc 调用中检测到第一个堆损坏。

有没有比为 allocations_map 编写非日志自定义分配器更优雅的解决方案?容器显然不应记录自己的分配。

我也按照评论中的建议尝试了两种单例方法,但没有成功:

allocations_map& get_allocations_map()
{
    static allocations_map* allocations_ptr = nullptr;
    if (allocations_ptr == nullptr)
    {
        allocations_ptr = (allocations_map*) malloc(sizeof(allocations_map));
        allocations_ptr = new(allocations_ptr)allocations_map;
    }
    return *allocations_ptr;
}


allocations_map& get_allocations_map()
{
    static allocations_map allocations;
    return allocations;
}

std::allocator::allocate 分配器分配 n“东西”不是 n 字节。你应该改变:

T* allocate(std::size_t n) const { return (T*)malloc(n); }

至:

T* allocate(std::size_t n) const { return (T*)malloc(sizeof(T) * n); }

Why do i corrupt the heap in the constructor of allocations_map?

因为存储在该映射中的元素的构造函数访问分配的内存out-of-bounds。