代码之家  ›  专栏  ›  技术社区  ›  Oriel Cochavi

编译器无法识别导致LNK2019的重载删除运算符

  •  2
  • Oriel Cochavi  · 技术社区  · 7 年前

    我用过 Pavel Yosifovich's article 使用c++开发windows内核驱动程序(不是出于特殊原因,只是为了研究它)。

    在他的文章中,Pavel展示了如何重载new和delete操作符以及如何实现vector。

    当我试图用重载的delete运算符编译驱动程序时,由于链接器错误(LNK2019)而失败,这是因为编译器没有编译正确的delete运算符。

    我的代码:

    Vector<ULONG> *vector = nullptr;
    
    void* __cdecl operator new(size_t size, POOL_TYPE pool, ULONG tag = 0) {
        return ExAllocatePoolWithTag(pool, size, tag);
    }
    void __cdecl operator delete(void* p) {
        ExFreePool(p);
    }
    
    NTSTATUS Init()
    {
        vector = (Vector<ULONG>*)new(NonPagedPool, 'DaOr') Vector<ULONG>();
    
        return STATUS_SUCCESS;
    }
    
    NTSTATUS Fin()
    {
        // case 1:
        delete vector;
        // case 2:
        // delete (void*)vector;
    
        return STATUS_SUCCESS;
    }
    

    有两种情况会导致不同的链接器错误消息:

    void运算符delete(void*,unsigned int) (VS2017年)。

    错误LNK2019未解析的外部符号“void”cdecl运算符 “public:void*\u此调用向量::`标量删除 析构函数'(unsigned int)'(??_G?$Vector@K@@QAEPAXI@Z)

    案例2中的错误:(在本例中,将鼠标悬停在Fin()中的delete运算符上,表明它是我的重载delete运算符 “void运算符删除(void*p)” (VS2017年)。

    删除(void*,unsigned int)“(??函数中引用了3@YAXPAXI@Z) “长鳍(空)”(?财务@@YGJXZ)

    在这两种情况下,链接器似乎都在查找同一个delete运算符,只是delete运算符是从不同的位置引用的。

    通过更改删除操作员的签名:

    void __cdecl operator delete(void*)
    

    void __cdecl operator delete(void*, unsigned int)
    

    编译器识别我的delete运算符。

    1. 为什么在案例1中,链接器搜索向量中的delete运算符?我可以理解编译器试图调用向量析构函数时的混乱,但我想要一个解释。

    2. 为什么在案例2中,当我将鼠标悬停在Fin()中的delete运算符上时,它显示“operator delete(void*)”,而错误显示“operator delete(void*,unsigned int)”?(我知道这可能是VS2017错误,但这可能是其他原因吗?)

    0 回复  |  直到 7 年前