c – 当用户调用operator new时,分配/对象详细信息拦截和收集问
我正在研究一种跟踪分配和解除分配,对象大小,对象类型等的小型内存工具.我用来跟踪源文件,行号和对象类型的方法是这样的:
#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); } }; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |