过载的新操作员问题

Overloaded new operator problems

本文关键字:操作员 问题      更新时间:2023-10-16

我决定重载new,new[],。。。运算符,这样我就可以记录调用它们的文件和行,这样我可以更容易地跟踪内存分配/泄漏。

现在问题出现在我的堆栈和数组类(以及其他分配内存的模板容器类(中:

如果我将它们与我的一个类一起使用,该类具有new,new[],。。。操作员超负荷工作,效果良好。

但是,如果我将其与标准c++数据类型(int、float…(一起使用,我就无法分配它们,因为没有重载的新运算符与new(__LINE___、__FILE__(运算符(或其他类似placement-new的运算符(的参数相匹配。

堆栈代码示例:

// placement new
T* t=new(__ LINE __ , __ FILE__)(&m_data[i])T;

所以我对如何使这项工作发挥作用没有什么好主意。如果我将新的(__行__,__文件__(替换为新的I松散内存日志记录功能。一种解决方案是为使用默认new的标准数据类型制作一个单独的堆栈。

是否有任何方法可以在编译时检测模板参数是结构、类还是内置的c++类型?

你是如何处理这样的事情的?你有什么建议?对这个设计的任何评论(好的,坏的(显然都是受欢迎的(只是不要发布"不要用自己的容器重新发明轮子"之类的东西(。

请注意,您当前的解决方案需要在每次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具有此功能,请参阅此处
-在的"跟踪内存泄漏"部分,有一个关于以这种方式进行内存跟踪的教程

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过载是一种黑色艺术,通常应该避免。

是否有任何方法可以在编译时检测模板参数是否为结构、类或一个内置的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为您的类型集