首页 > 解决方案 > 找不到匹配的运算符删除;如果初始化抛出异常,内存将不会被释放

问题描述

我创建了一个覆盖新(和删除)运算符的 BaseObject 类,因此我可以在应用程序生命周期中创建和销毁内存时记录内存,使我可以轻松发现任何未释放的内存。

但是,编译时出现以下错误(但运行良好):

resourcemanager.h(36): 警告 C4291: 'void *BaseObject::operator new(size_t,const char *,int)': 找不到匹配的运算符删除;如果初始化抛出异常,内存将不会被释放

baseobject.h(8):注意:参见“BaseObject::operator new”的声明

我的 BaseObject 类如下所示:

class BaseObject
{
public:
    void* operator new(size_t size, const char* file, int line);
    void* operator new[](size_t size, const char* file, int line);

    void operator delete(void* ptr);
    void operator delete[](void* ptr);
};

#define MY_NEW new(__FILE__, __LINE__)
#define MY_DELETE delete(__FILE__, __LINE__)

从我在互联网上阅读的内容来看,问题是由于被覆盖的删除运算符需要匹配的签名。所以在这种情况下,如果我将“const *char file, int line”添加到删除运算符,它应该可以工作。但是后来我遇到了另一个问题,因为我无法在任何对象上调用 delete,因为它没有找到匹配的删除运算符(它现在必须将文件和行作为输入)。在这种情况下,使用上面的 MY_DELETE 宏不起作用,因为 delete 不能使用这样的参数。

在这里几乎是不知所措。

编辑:

解决方案不是立即显而易见的。添加具有与新函数相同的额外参数的重写删除函数是不够的,因为这会产生“没有非放置删除运算符”的问题。这反过来可以通过添加非放置删除运算符来解决。所以,这个类现在看起来像这样(并且它正在工作):

class BaseObject
{
public:
    void* operator new(size_t size, const char* file, int line);
    void* operator new[](size_t size, const char* file, int line);

    // Placement delete functions, matching overridden new functions
    void operator delete(void* ptr, const char* file, int line);
    void operator delete[](void* ptr, const char* file, int line);

    // Non-placement delete functions
    void operator delete(void* ptr);
    void operator delete[](void* ptr);
};

标签: c++

解决方案


从 cppreference https://en.cppreference.com/w/cpp/language/new

如果初始化通过抛出异常终止(例如从构造函数),如果 new-expression 分配了任何存储,它调用适当的释放函数:operator delete对于非数组类型, operator delete[]对于数组类型。如果 new-expression 使用语法,则在全局范围内查找释放函数::new,否则在 的范围内查找T,如果T是类类型。如果失败的分配函数是通常的(非放置),则查找释放函数遵循删除表达式中描述的规则。对于一个失败的placement new,匹配解除分配函数的所有参数类型,除了第一个,必须与placement new 的参数相同。对解除分配函数的调用是先前从分配函数获得的值,作为第一个参数传递,对齐作为可选alignment参数传递(C++17 起),placement_params如果有的话,作为附加放置参数传递。如果没有找到释放函数,则不会释放内存。

因此,在您的情况下,删除的匹配签名是:

  1. 剥离size
  2. 放在void* ptr它的位置
  3. 重复传递给的参数operator new

这将导致:

class BaseObject
{
public:
    void* operator new(size_t size, const char* file, int line);
    void* operator new[](size_t size, const char* file, int line);

    void operator delete(void* ptr, const char* file, int line);
    void operator delete[](void* ptr, const char* file, int line);
};

题外话:abstract 不是 C++ 中的关键字,这应该是编译错误。要使类抽象,请将函数定义为纯虚拟(通过将= 0其作为定义)。


推荐阅读