You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

全局作用域定义void* operator new(std::size_t)为何不引发多重定义链接错误?

为什么自定义全局operator new不会和libstdc++的实现冲突?

问题场景

以下代码可以正常编译运行,但按常理libstdc++应该也定义了一个同名同签名的全局作用域函数,为何不会引发冲突?

// main.cpp
#include <iostream>
#include <new>

void* operator new(std::size_t size) {
    std::cout << "Custom new called for size: " << size << " bytes" << std::endl;

    // Call malloc to allocate memory.
    void* ptr = std::malloc(size);

    return ptr;
}

int main() {
    int* p = new int;
    double* q = new double[10];

    delete p;
    delete[] q;

    return 0;
}

编译运行输出:

$ g++ --version && g++ -g ./main.cpp && ./a.out
g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Custom new called for size: 4 bytes
Custom new called for size: 80 bytes

原因解析

核心原因是C++标准允许用户替换全局作用域的operator new,而libstdc++完全遵循这个规则实现:

  • C++标准明确赋予用户合法权限:可以在全局作用域定义与标准签名一致的operator new,以此替换标准库的默认内存分配逻辑。
  • libstdc++中的全局operator new是用**弱符号(weak symbol)**标记的(通过GCC的__attribute__((weak))属性)。链接阶段,当存在同名的强符号(即你自定义的operator new)时,链接器会优先选用强符号,自动忽略弱符号版本,因此不会出现符号冲突。
  • 你代码里的自定义operator new属于强符号,链接时直接覆盖了libstdc++的弱符号版本,所以程序运行时会调用你的实现。

额外补充:你只替换了普通版本的operator new,但数组分配new double[10]也触发了自定义逻辑,是因为libstdc++的默认operator new[]内部会调用普通的operator new,所以间接用到了你的自定义实现。


内容的提问来源于stack exchange,提问作者StoneThrow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 00:46:23