我决定在我的类中重载new,new [],...运算符,这样我就可以记录它们被调用的文件和行,这样我就可以更轻松地跟踪内存分配/泄漏。
现在问题出现在我的堆栈和数组类(以及分配内存的其他模板容器类)中:
如果我将它们与我的一个具有new,new [],...运算符的类一起使用它可以正常工作。
但是如果我将它与标准的c ++数据类型(int,float,...)一起使用,我就无法分配它们,因为没有重载的new运算符匹配new的参数(__ LINE __,__ FILE __)运营商(或其他类似新职位)。
堆栈代码示例:
// placement new
T* t=new(__ LINE __ , __ FILE__)(&m_data[i])T;
所以我对如何使这项工作有好主意。如果我用新的松散内存记录功能替换new(__ LINE __,__ FILE __)。 一种解决方案是为标准数据类型创建一个分离的堆栈,其中使用了默认的new。
有没有办法在编译时检测模板参数是结构,类还是内置的c ++类型?
你如何处理这样的事情? 你有什么建议? 对这种设计的任何评论(好的,坏的)显然都是受欢迎的(只是不要张贴诸如“不要用自己的容器重新发明轮子”这样的东西。)
答案 0 :(得分:1)
请注意,您当前的解决方案需要将日志记录代码添加到您拥有的每个 new(line, file)
超载。此外,除非您在#ifndef DEBUG ... #endif
内包围每个日志记录调用,否则无法在发布版本中轻松将其关闭。
这是实现目标的一种方法:不要为每个类重载new
运算符,而应考虑使用放置语法重载全局new
运算符;这样你就可以避免干扰'普通'new
运算符。然后,您可以#define
新增和删除宏以方便使用,最重要的是,您可以控制何时应用内存跟踪new/delete
以及何时使用标准版本。
#ifdef ENABLE_CUSTOM_ALLOC
// Custom new operator. Do your memory logging here.
void* operator new (size_t size, char* file, unsigned int line)
{
void* x = malloc(size);
cout << "Allocated " << size << " byte(s) at address " << x
<< " in " << file << ":" << line << endl;
return x;
}
// You must override the default delete operator to detect all deallocations
void operator delete (void* p)
{
free(p);
cout << "Freed memory at address " << p << endl;
}
// You also should provide an overload with the same arguments as your
// placement new. This would be called in case the constructor of the
// created object would throw.
void operator delete (void* p, char* file, unsigned int line)
{
free(p);
cout << "Freed memory at address " << p << endl;
}
#define new new(__FILE__, __LINE__)
#endif
// A test class with constructors and destructor
class X
{
public:
X() { cout << "X::ctor()" << endl; }
X(int x) { cout << "X::ctor(" << x << ")" << endl; }
~X() { cout << "X::dtor()" << endl; }
};
int main (int argc, char* argv[])
{
X* x3 = new X();
X* x4 = new X(20);
delete x3;
delete x4;
}
你应该看到类似的东西:
Allocated 1 byte(s) at address 00345008 in Alloc.cpp:58
X::ctor()
Allocated 1 byte(s) at address 003450B0 in Alloc.cpp:59
X::ctor(20)
X::dtor()
Freed memory at address 00345008
X::dtor()
Freed memory at address 003450B0
尝试用X
代替int
,你会发现它也有效。您可以将此扩展到数组和放置新的,但我宁愿不使帖子比它更长。
最后几点指示:
- MSVC具有此功能,请参阅here
- 在“跟踪内存泄漏”部分下以here方式进行内存跟踪是一件很有意思的事情
答案 1 :(得分:0)
struct Int {
int i;
Int (int _i) : i(_i) {}
operator int () const {return i;}
};
#define __LINE_NUMBER__ Int(__LINE__)
使用此宏代替标准行号宏,重载分辨率会将Int
行号与int
其他数字区分开来。
我无法想象这将如何全面发挥作用。你打算像int * x = NEW(int,123);
那样使用它吗?
顺便说一句,我同意评论者的意见 - 你可能不必走这条路。重载new
是一种黑色艺术,通常应该避免。
答案 2 :(得分:0)
有没有办法在编译时检测模板参数是结构,类还是 内置的c ++类型?
你可以使用boos :: type_traits和boost :: mpl。
示例:
#include <boost/type_traits.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/logical.hpp>
template <class T>
typename boost::enable_if<boost::is_class<T>, T>::type
foo(){cout << "is class " << endl;};
template <class T>
typename boost::enable_if<boost::mpl::not_<boost::is_class<T> >, T>::type
foo(){cout << "is not class "<< endl;};
类型列表 - http://www.boost.org/doc/libs/1_47_0/libs/type_traits/doc/html/index.html
或者您可以将boost :: mpl :: set用于您的类型集