代码之家  ›  专栏  ›  技术社区  ›  One_Cable5781

/MSVC cl.exe中的内核模式允许new,尽管指定了用户必须显式定义运算符

  •  3
  • One_Cable5781  · 技术社区  · 6 月前

    根据 documentation /kernel

    您必须明确定义 new() delete() 操作员。这

    然而,以下代码编译并运行良好,没有任何错误。

    #include <iostream>
    
    int main(){
        int* xyz = new int[10];
        std::cout<<"Hello!";
    }
    

    请点击此处查看godbolt链接: https://godbolt.org/z/96MTMcYeT

    (Q2)在godbolt中,有没有一种方法可以指定链接器标志,而不仅仅是编译标志?

    2 回复  |  直到 6 月前
        1
  •  2
  •   RbMm    6 月前

    /kernel 编译器选项对任何形式的 new delete .编译器从不提供任何形式的默认实现 因此,它必须在某个地方实施。在某些 .lib 您添加到链接器输入或通过代码添加的文件。

    为什么代码编译正确,这似乎与官方文档相悖?

    为什么它不能编译??甚至“官方文档”也没有说代码不能编译。编译可以识别new和delete,而无需外部声明。

    另一个问题是链接。

    如果你使用这样的代码

        if (int* p = new int)
        {
            delete p;
        }
    

    new int 作为呼叫 ??2@YAPEAX_K@Z delete p 作为 ??3@YAXPEAX_K@Z .当你链接时,链接器将在它的输入文件(obj,lib)中搜索这2个符号,如果找不到,你会得到这样的错误:

    error LNK2001: unresolved external symbol "void * __cdecl operator new(unsigned __int64)" (??2@YAPEAX_K@Z)
    error LNK2001: unresolved external symbol "void __cdecl operator delete(void *,unsigned __int64)" (??3@YAXPEAX_K@Z)
    

    void* __cdecl operator new(size_t ByteSize)
    {
        return LocalAlloc(0, ByteSize);
    }
    
    void __cdecl operator delete(void* Buffer,unsigned __int64)
    {
        LocalFree(Buffer);
    }
    

    我怎么说 /内核 在这里没有任何效果。有和没有 /内核 你需要实现 2.YAPEAX_K@Z 等等。

    在用户模式下,我们可以使用msvcrt.lib(或libcmt.lib)。如果我们为内核模式构建,则不能使用msvcrt.lib,并且任何wdk库都不提供以下实现 2.YAPEAX_K@Z new() delete() LocalAlloc 但随着 ExAllocatePool (其中一种变体)。

    如果我们使用“/kernel”编译器/链接器开关,这并不意味着我们构建了内核模式二进制文件。我们可以用它构建和用户模式二进制文件。反之亦然-我们可以在有或没有/kernel开关的情况下构建内核模式二进制文件

        2
  •  0
  •   BoP    6 月前

    微软的文档在使用“ new() 当他们真正的意思是 operator new(size_t) .

    https://en.cppreference.com/w/cpp/memory/new/operator_new

    困惑(和Bjarne new operator new 分配内存,然后使用类型的构造函数(如果有的话)初始化数据。

    运算符内置于语言中,用户无法重新定义。然而,分配部分 operator new[](size_t) 对于内核代码,你显然 到。

    假设Godbolt没有在Windows内核中运行代码,您不会注意到那里缺少这些运算符。

    推荐文章