在 cpp 中重新定义 new 和 delete 运算符以跟踪内存分配:无法跟踪整个内存块的删除大小

Posted

技术标签:

【中文标题】在 cpp 中重新定义 new 和 delete 运算符以跟踪内存分配:无法跟踪整个内存块的删除大小【英文标题】:redefining new and delete operators in cpp for tracking memory allocations: cannot track size of delete of whole memory blocks 【发布时间】:2021-03-13 20:18:52 【问题描述】:

我想在 C++ 中重新定义一些 new 和 delete 操作符,以尝试和跟踪内存分配/释放,类似这样的东西:

#include <iostream>
#include <vector>

void* operator new(std::size_t n) 
    std::cout << "[Allocate " << n << " bytes]";
    void * ptr_out = malloc(n);
    std::cout << " at addr " << ptr_out << std::endl;
    return ptr_out; 


void operator delete(void* p) throw() 
    std::cout << "[Free 1  byte] at addr " << p << std::endl;
    free(p);


void operator delete(void* p, std::size_t nbr_bytes) throw() 
    std::cout << "[Free " << nbr_bytes << " bytes] at addr " << p << std::endl;
    free(p);


int main()

    std::cout << "small vector" << std::endl;
    std::vector<int> vec_1 1, 2, 3, 4;

我能够很好地拦截内存分配(新),但是我无法以显示整个内存块已释放的方式拦截内存释放(删除),即我得到:

small vector
[Allocate 16 bytes] at addr 0x55b1c5d84280
[Free 1  byte] at addr 0x55b1c5d84280

虽然我真的想表明当程序返回时程序释放了向量的全部 16 个字节。

知道我是否/如何做到这一点,即打印以下内容吗?

small vector
[Allocate 16 bytes] at addr 0x55b1c5d84280
[Free 16  bytes] at addr 0x55b1c5d84280

【问题讨论】:

您需要自己记账,因为无法从 void * 获取分配的大小 您可能需要创建一个自定义类,您可以在其中执行上述操作,并在内存中跟踪其内容的确切大小... 实现将大小保持在某处,但它是实现定义的行为。 与msvc相关:https://***.com/questions/4955399/visual-studio-2010-c-get-size-of-memory-block-allocated-by-malloc https://***.com/questions/852072/simple-c-implementation-to-track-memory-malloc-free 这个答案建议使用一个库来为您进行跟踪:https://***.com/a/852532/487892 【参考方案1】:

当删除不完整类型的对象以及非类和可简单破坏的类类型(ref1、ref2)的数组时,将调用哪些 operator delete 重载由实现定义。

Vector 可能正在分配 chars 或类似的,因此您必须遵守此规则。

您可以使用nbr_bytes 参数来提高效率如果你得到它,但如果你想保证访问,你必须自己存储信息给它。

如果您使用std::map 这样做,请注意不要将自己写成递归灾难?。

【讨论】:

好的,所以你的意思是调用哪个删除操作符是特定于实现的,对吧?但是,我不明白如何在 addr 0x55b1c5d84280 处打印出 [Free 1 byte] 消息;这意味着我重新定义的删除运算符已被以某种方式调用。 @Zorglub29 是的,但你的第一个,而不是你的第二个。你不能依赖第二个被调用。 好的,谢谢,我想我明白了。问题是,在我的范围之外,有一些关于存储块的元数据,对吧? :) 。这听起来有点棘手。 嗯,是的,也不是。从这些运算符的角度来看,不,除了operator new 的参数之外,任何地方都不存在这样的元数据,这完全是重点:它不存在因为您没有将其存储以供以后使用采用。但是,由于您将实际分配委托给mallocfree,我们可以讨论那些 东西可能存储的数据类型,在典型平台上答案变为“是”只要您确实委派了这些分配功能。

以上是关于在 cpp 中重新定义 new 和 delete 运算符以跟踪内存分配:无法跟踪整个内存块的删除大小的主要内容,如果未能解决你的问题,请参考以下文章

cpp小知识点 —— new 和 delete的误区

CPP游戏攻略03

Item 50:为什么需要自定义new和delete?

Item 50:为什么需要自定义new和delete?

Item 50:为什么需要自定义new和delete?

g ++用户定义的动态链接库上的全局new和delete运算符