加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 当用户调用operator new时,分配/对象详细信息拦截和收集问

发布时间:2020-12-16 06:55:12 所属栏目:百科 来源:网络整理
导读:我正在研究一种跟踪分配和解除分配,对象大小,对象类型等的小型内存工具.我用来跟踪源文件,行号和对象类型的方法是这样的: #define DEBUG_NEW SourcePacket(__FILE__,__LINE__) * new#define new DEBUG_NEW SourcePacket只是一个小类,它在构造过程中采用cons
我正在研究一种跟踪分配和解除分配,对象大小,对象类型等的小型内存工具.我用来跟踪源文件,行号和对象类型的方法是这样的:

#define DEBUG_NEW SourcePacket(__FILE__,__LINE__) * new
#define new DEBUG_NEW

SourcePacket只是一个小类,它在构造过程中采用const char *和int.这些值通过__FILE__和__LINE__宏填充.获取对象类型如下:

template<typename T>
T* operator*(const SourcePacket& packet,T* p);

p是指向新分配对象的指针,该对象的类型是使用RTTI发现的.在运算符重载中,获取信息并将其存储在跟踪器中,并将指针传递给程序.在重载的operator new中抓取了大小和地址等更多信息.

现在,这个设置对我来说非常有效.它自然不适用于我不编译的代码,但最好的事情之一就是它可以很好地放置用户发出的新调用,但是使用经常引用的调用不起作用

#define new new(__FILE__,__LINE__)

方法.我遇到的问题是,如果用户调用operator new,程序就无法编译.当然,这是因为宏如此扩展

return operator SourcePacket("blahblah.cpp",20) * new(size);

代替

return SourcePacket("blahblah.cpp",20) * new(size);

我真的看不到任何解决方法.当然,我可以删除SourcePacket *新程序,让我的重载运算符new收集大小和地址,但这种方法会破坏该工具的很大一部分用途.

(另外,作为一个注释,我不是要创建Valgrind或任何东西,我知道重载全局操作可能相当狡猾.这主要是出于教育目的.此外,我知道特定于操作系统的功能可以用于发现一些这样的信息,但我只想使用标准的C,以便它是跨平台和位独立的(x86,x64等).到目前为止,它在Linux上对我来说完美无缺和Windows版本的两种口味.)

不幸的是,似乎没有任何方式有条件地使用这种或那种方式,这取决于它是新的(或新的位置)还是新的操作符.我让这个工作起作用并不重要,但我很想知道是否有人找到解决这个限制的方法.

解决方法

我们需要一个在以“operator”作为前缀时有效的表达式.这意味着我们需要定义一个采用SourcePacket的运算符.它可能需要其他参数,但事实证明这不是必要的.一元运算符*会做得很好:

const SourcePacket& operator *(const SourcePacket& sp)  {
    return sp;
}

#define DEBUG_NEW *(SourcePacket(__FILE__,__LINE__)) * new
#define new DEBUG_NEW

由于我们无法完全括起语句,因此除了最简单的表达式之外,还有可能出现错误.

struct Chain {
  Chain() : next(0) {}
  Chain(Chain *n) : next(n) {}
  ~Chain() {delete next;}
  Chain* next; 
  Chain& operator *(Chain* b);
};
Chain& Chain::operator *(Chain* b) { 
   if (b != next) {
     if (next) { delete next; }
     next = b;
   }
   return *this; 
}

int main() {
  Chain fetters;
  /* since * is left associative,it tries to 
     call operator*(Chain&,const SourcePacket&)
     */
  fetters * new Chain();
  // This compiles
  fetters * (new Chain());
}

要解决此问题,我们需要定义适当的运算符.对于返回类型,您可以定义模板类的层次结构,该模板类将左参数与SourcePacket配对并且在右参数中是可交换的((a:A⊙b:SourcePacket)* c:C)=(a:A⊙c :C)* b:SourcePacket,其中⊙是一些二进制C运算符).像下面这样的东西,但没有它无疑拥有的错误.

template <typename L,typename Rslt=L,typename R=const SourcePacket> 
struct PairedTraits {
    typedef L Left;
    typedef R Right;
    typedef Rslt Result;
    typedef PairedTraits<Result> ResultTraits;
};

template <typename L,typename Traits = PairedTraits<L> >
struct Paired {
    typedef typename Traits::Left Left;
    typedef typename Traits::Right Right;
    typedef typename Traits::Result Result;
    typedef Paired<typename Traits::Result,typename Traits::ResultTraits> ResultPaired;

    Left& left;
    Right& right;

    Paired(Left& l,Right& r) : left(l),right(r) {} 
    operator Left&() {return left;}

    template <typename A>
    ResultPaired  operator*(const C& c) const
    {return ResultPaired(this->left * c,this->right); }
};

template <typename L,typename Traits = PairedTraits<L> >
struct MultPaired : Paired<L,Traits> {
    typedef Paired<L,Traits> Base;
    typedef Paired<typename Traits::Result,typename Traits::ResultTraits> ResultPaired;

    MultPaired(typename Traits::Left& l,typename Traits::Right& r) : Base(l,r) {} 

    template <typename A>
    ResultPaired  operator*(const C& c) const
    {return ResultPaired(this->left * c,typename Traits = PairedTraits<L> >
struct ModPaired : Paired<L,typename Traits::ResultTraits> ResultPaired;

    ModPaired(typename Traits::Left& l,r) {} 

    template <typename A>
    ResultPaired operator*(const C& c) 
    {return ResultPaired(this->left % c,typename Traits = PairedTraits<L> >
struct DivPaired : Paired<L,Traits> {
    typedef Paired<Traits> Base;
    typedef Paired<typename Traits::Result,typename Traits::ResultTraits> ResultPaired;

    DivPaired(typename Traits::Left& l,r) {} 

    template <typename A>
    ResultPaired operator*(const C& c) const
    {return ResultPaired(this->left / c,this->right); }
};

配对的孩子可以返回一个结果(左⊙c,或左⊙(右* c),这基本上使*(const SourcePacket&,T)右关联)而不是配对.例如:

template <typename L,Traits> Base;

    MultPaired(typename Traits::Left& l,r) {} 

    template <typename A>
    Result  operator*(const C& c) const
    {return this->left / (this->right * c); }
};

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读