函数的返回类型是重整名称的一部分吗?

2023-11-27

假设我有两个具有相同参数类型和名称的函数(不在同一个程序中):

std::string foo(int x) {
  return "hello"; 
}

int foo(int x) {
  return x;
}

编译后它们会具有相同的损坏名称吗?

返回类型是 C++ 中重整名称的一部分吗?


由于破坏方案没有标准化,因此这个问题没有单一的答案;最接近实际答案的方法是查看由最常见的损坏方案生成的损坏名称。据我所知,这些是 GCC 和 MSVC 方案,按字母顺序排列,所以......


GCC:

为了测试这一点,我们可以使用一个简单的程序。

#include <string>
#include <cstdlib>

std::string foo(int x) { return "hello"; }
//int         foo(int x) { return x; }

int main() {
    // Assuming executable file named "a.out".
    system("nm a.out");
}

使用 GCC 或 Clang 编译并运行,它会列出它包含的符号。根据取消注释的函数,结果将是:

// GCC:
// ----

std::string foo(int x) { return "hello"; } // _Z3fooB5cxx11i
                                             // foo[abi:cxx11](int)
int         foo(int x) { return x; }       // _Z3fooi
                                             // foo(int)

// Clang:
// ------

std::string foo(int x) { return "hello"; } // _Z3fooi
                                             // foo(int)
int         foo(int x) { return x; }       // _Z3fooi
                                             // foo(int)

GCC方案包含的信息相对较少,不包括返回类型:

  • 符号类型:_Z为“功能”。
  • Name: 3foo for ::foo.
  • 参数:i for int.

然而,尽管如此,当用 GCC 编译时它们是不同的(但用 Clang 则不然),因为 GCC 表明std::string版本使用cxx11 ABI.

请注意,它仍然跟踪返回类型,并确保签名匹配;它只是不使用函数的损坏名称来执行此操作。


MSVC:

为了测试这一点,我们可以使用一个简单的程序,如上所述。

#include <string>
#include <cstdlib>
    
std::string foo(int x) { return "hello"; }
//int         foo(int x) { return x; }
    
int main() {
    // Assuming object file named "a.obj".
    // Pipe to file, because there are a lot of symbols when <string> is included.
    system("dumpbin/symbols a.obj > a.txt");
}

使用 Visual Studio 编译并运行,以及a.txt将列出它包含的符号。根据取消注释的函数,结果将是:

std::string foo(int x) { return "hello"; }
  // ?foo@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@Z
  // class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl foo(int)
int         foo(int x) { return x; }
  // ?foo@@YAHH@Z
  // int __cdecl foo(int)

MSVC 方案包含整个声明,包括未明确指定的内容:

  • Name: foo@ for ::foo, 其次是@终止。
  • 符号类型:名称终止后的所有内容@.
  • 类型和会员状态:Y对于“非成员函数”。
  • 调用约定:A for __cdecl.
  • Return type:
    • H for int.
    • ?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@(其次是@终止)对于std::basic_string<char, std::char_traits<char>, std::allocator<char>> (std::string简称)。
  • 参数表:H for int(其次是@终止)。
  • 异常说明符:Z for throw(...);除非是其他名称,否则该名称会从分解名称中省略,可能是因为 MSVC 无论如何都会忽略它。

如果每个编译单元的声明不相同,它就会向您抱怨。


一般来说,大多数编译器在分别针对 *nix 或 Windows 时会使用这些方案之一(有时是其变体),但这并不能保证。例如...

  • 据我所知,Clang 将使用 *nix 的 GCC 方案,或 Windows 的 MSVC 方案。
  • Intel C++ 对 Linux 和 Mac 使用 GCC 方案,对 Windows 使用 MSVC 方案(有一些细微的变化)。
  • Borland 和 Watcom 编译器有自己的方案。
  • Symantec和Digital Mars编译器通常使用MSVC方案,有一些小的变化。
  • 旧版本的 GCC 和许多 UNIX 工具使用 cfront 的重整方案的修改版本。
  • 等等...

Schemes used by other compilers are thanks to Agner Fog's PDF.


Note:

检查生成的符号,很明显 GCC 的损坏方案无法提供与 MSVC 相同级别的针对马基雅维利的保护。考虑以下:

// foo.cpp
#include <string>

// Simple wrapper class, to avoid encoding `cxx11 ABI` into the GCC name.
class MyString {
    std::string data;

  public:
    MyString(const char* const d) : data(d) {}

    operator std::string() { return data; }
};

// Evil.
MyString foo(int i) { return "hello"; }

// -----

// main.cpp
#include <iostream>

// Evil.
int foo(int);

int main() {
    std::cout << foo(3) << '\n';
}

如果我们单独编译每个源文件,然后尝试将目标文件链接在一起......

  • GCC: MyString,由于不属于cxx11ABI,原因MyString foo(int)被毁坏为_Z3fooi, 就像int foo(int)。这允许链接目标文件,并生成可执行文件。尝试运行它会导致段错误。
  • MSVC:链接器将寻找?foo@@YAHH@Z;因为我们提供了?foo@@YA?AVMyString@@H@Z,链接将会失败。

考虑到这一点,包含返回类型的重整方案更安全,即使函数不能仅根据返回类型的差异进行重载。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

函数的返回类型是重整名称的一部分吗? 的相关文章

  • WPF 中的屏幕分辨率问题?

    我将在 WPF 中使用以下代码检测分辨率 double height System Windows SystemParameters PrimaryScreenHeight double width System Windows Syste
  • 通过增加索引之和来生成排序组合的有效方法

    对于启发式算法 我需要一个接一个地评估特定集合的组合 直到达到停止标准 由于它们很多 目前我正在使用以下内存高效迭代器块生成它们 受到 python 的启发 itertools combinations http docs python o
  • 内联函数/方法

    声明 内联函数必须在调用之前定义 这个说法正确吗 EDIT 该问题最初是德语 内联功能穆森 弗 伊赫雷姆 奥夫鲁夫定义 sein 也许它对任何人都有帮助 是的 它是正确的 但只是部分正确 它可能正确地重新构建如下 内联函数必须在每个翻译单位
  • System.IO.IOException:由于意外>数据包格式,握手失败?

    有谁知道这意味着什么 System Net WebException 底层连接已关闭 发送时发生意外错误 gt System IO IOException 由于意外 握手失败 数据包格式 在 System Net Security SslS
  • 为什么大多数平台上没有“aligned_realloc”?

    MSVC有自己的非标准函数 aligned malloc aligned realloc and aligned free C 17和C11引入了 std aligned alloc 其结果可以是de分配有free or realloc B
  • C# 正则表达式用于查找 中具有特定结尾的链接

    我需要一个正则表达式模式来查找字符串 带有 HTML 代码 中的链接 以获取文件结尾如 gif 或 png 的链接 示例字符串 a href site com folder picture png target blank picture
  • 如何创建用于 QML 的通用对象模型?

    我想知道是否有任何宏或方法如何将 Qt 模型注册为 QObject 的属性 例如 我有AnimalModel http doc qt io qt 5 qtquick modelviewsdata cppmodels html qabstra
  • 劫持系统调用

    我正在编写一个内核模块 我需要劫持 包装一些系统调用 我正在暴力破解 sys call table 地址 并使用 cr0 来禁用 启用页面保护 到目前为止一切顺利 一旦完成 我将公开整个代码 因此如果有人愿意 我可以更新这个问题 无论如何
  • 将带有 glut 的点击坐标添加到向量链接列表中

    我想创建一个向量链接列表 并在 GLUT 库的帮助下获取点击的位置并将它们附加到链接列表中 这些是我写的结构 typedef struct vector int x int y Vector typedef struct VectorLis
  • 两种类型的回发事件

    1 我发现了两篇文章 每篇文章对两种类型的回发事件的分类都略有不同 一位资源说两种类型的回发事件是Changed事件 其中控件实现 IPostbackDataHandler 当数据在回发之间更改时触发 然后Raised事件 其中控件实现 I
  • 从 Code::Blocks 运行程序时出现空白控制台窗口 [重复]

    这个问题在这里已经有答案了 当我尝试在 Code Blocks 中构建并运行新程序时 控制台窗口弹出空白 我必须单击退出按钮才能停止它 它对我尝试过的任何新项目 包括 Hello world 都执行此操作 奇怪的是 它对于我拥有的任何旧项目
  • 2D morton 码编码/解码 64 位

    如何将给定 x y 的莫顿代码 z 顺序 编码 解码为 32 位无符号整数 生成 64 位莫顿代码 反之亦然 我确实有 xy2d 和 d2xy 但仅适用于 16 位宽的坐标 产生 32 位莫顿数 在网上查了很多 但没有找到 请帮忙 如果您可
  • 分配器感知容器和propagate_on_container_swap

    The std allocator traits模板定义了一些常量 例如propagate on container copy move assign让其他容器知道它们是否应该在复制或移动操作期间复制第二个容器的分配器 我们还有propag
  • asp.net网格分页的SQL查询

    我在用iBatis and SQLServer 使用偏移量和限制进行分页查询的最佳方法是什么 也许我添加该列ROW NUMBER OVER ORDER BY Id AS RowNum 但这只会阻止简单查询的数据访问 在某些情况下 我使用选择
  • 为什么要在 C++ 中使用 typedef?

    可以说我有 set
  • WPF。如何从另一个窗口隐藏/显示主窗口

    我有两个窗口 MainWindow 和 Login 显示登录的按钮位于主窗口 this Hide Login li new Login li Show 登录窗口上有一个检查密码的按钮 如果密码正确 我如何显示主窗口 将参数传递给 MainW
  • DataTable:通过 LINQ 或 LAMBDA 进行动态 Group By 表达式

    我有一个数据表 我想在其中对未指定数量的字段进行分组 发生这种情况的原因是用户可以选择他想要分组的字段 所以 实际上 我将选择推入列表中 在这个选择上 我必须对我的数据表进行分组 想象一下这段代码 VB 或 C 都一样 public voi
  • 0-1背包算法

    以下 0 1 背包问题是否可解 浮动 正值和 浮动 权重 可以是正数或负数 背包的 浮动 容量 gt 0 我平均有 这是一个相对简单的二进制程序 我建议用蛮力进行修剪 如果任何时候你超过了允许的重量 你不需要尝试其他物品的组合 你可以丢弃整
  • 如何引用解决方案之外的项目?

    我有一个 Visual Studio C 解决方案 其中包含一些项目 其中一个项目需要引用另一个不属于解决方案的项目 一开始我引用了dll
  • 在 C++17 中使用 成员的链接错误

    我在 Ubuntu 16 04 上使用 gcc 7 2 并且需要使用 C 17 中的新文件系统库 尽管确实有一个名为experimental filesystem的库 但我无法使用它的任何成员 例如 当我尝试编译此文件时 include

随机推荐

  • 结合 R Markdown 和动画包

    有没有办法结合起来animation package和 r 降价 我想生成动画 我想在从 r markdown 生成的 html 文件中包含和描述该动画 当然我可以嵌入代码saveHTML or saveGIF文件已生成的 r markdo
  • Windows 中 TEMP 目录的限制?

    我有一个用 Python 编写的应用程序 它将大量数据写入 TEMP 文件夹 奇怪的是 每隔一段时间 它就会死去 然后回来IOError Errno 28 No space left on device 该驱动器有plenty的自由空间 T
  • 在 Linux 上通过 jenkins 运行 angular2 测试时出现 Karma 错误

    使用 karma 和 jenkins 运行我的 angular2 单元测试时 我看到以下错误 当我在本地计算机 Windows 上运行测试时 我的测试运行良好 但是当在 Linux 上通过 jenkins 运行测试时 我收到以下错误 Mis
  • 如何在WPF MVVM中调用窗口的Loaded事件?

    从我的 OnLoaded 事件创建命令很容易 处理程序代码 但如何从视图中调用它 从此不再切蛋糕 它调用 xaml cs 中的代码 我将如何创建一个 ICommand 相等的 您可以通过附加行为来完成此类事情 为了节省一些时间 看看 Mar
  • Promise.all() 被拒绝后的值,显示 [''PromiseStatus'']:如果存在 catch 块,则已解决

    我有两个承诺 一个被拒绝 另一个被解决 Promise all 被调用 当其中一个承诺被拒绝时 它执行了 Promise all 的 catch 块 const promise1 Promise resolve Promise 1 Reso
  • GTK 或 Qt 的图表小部件 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 GTK 或 Qt 是否有一
  • NuGet 包依赖项

    对于一个包对其他库的每个依赖项 这些库是否也需要解析和安装 例如 我创建了一个使用的包NLog Postsharp and WindowsAzure Storage 我的软件包的客户端现在也必须安装这些软件包吗 为什么不能将这些依赖项 DL
  • 没有可见的接口错误

    我的模型的实现文件中有一个错误 我已将其注释掉 我可以做什么来解决这个问题 提前致谢 import CalculatorBrain h interface CalculatorBrain property nonatomic strong
  • 为什么在 `array.length && ...` 的短路计算中呈现“0”

    目前 我看到这样的行为 render const list return div list length div List rendered div div 我的预期是在该条件下不会呈现任何内容 但会呈现字符串 0 字符串 0 是list
  • spring-mvc中如何传递参数来重定向页面

    我写了以下控制器 RequestMapping value logOut method RequestMethod GET public String logOut Model model RedirectAttributes redire
  • 检查在自定义 Chrome 选项卡中打开哪个网址

    chrome自定义选项卡中是否有类似于Webview的onPageStarted的功能 在 onNavigation 捆绑包始终为空 根据设计 Chrome 自定义选项卡不可能做到这一点 您可以知道用户已经导航 但无法知道他们去了哪里 看
  • 检测浏览器关闭/导航到其他页面并注销的最佳方法

    我正在 GWT 中编写一个应用程序 我需要检测用户何时离开我的应用程序或何时关闭浏览器窗口 onUnload 事件 并执行注销 会话失效和其他一些清理任务 注销操作由 servlet 执行 我目前正在通过挂钩 onUnload 事件并打开一
  • 检查 LatLngBounds.Builder 是否为空

    这是我的代码 LatLngBounds Builder builder new LatLngBounds Builder for int x firstVisibleItem x lt lastVisibleItem x builder i
  • 如何提取直接 Facebook 视频 url

    我正在尝试从 facebook 视频链接中提取 facebook 视频文件页面的 url 但我无法继续操作 例如 我的 Facebook 视频网址是 https www facebook com nerdandco videos 16621
  • 如何在 Woocommerce 中检查产品是否具有特定产品属性

    我想确定产品是否具有属性 例如 if product has attribute pa color do something 我怎样才能做到这一点 您只需使用WC Product method get attribute 这边走 If ne
  • 在 keras 中加载模型后的不同预测

    我在 Keras 中构建了一个序列模型 经过训练后它给了我很好的预测 但是当我保存然后加载模型时 我没有在同一数据集上获得相同的预测 为什么 请注意 我检查了模型的权重 它们以及模型的架构都是相同的 并使用 model summary 和
  • 使用 Java 邮件服务器进行测试

    我正在测试一个应用程序 该应用程序从邮箱中取出邮件 根据该邮件的内容执行某些操作 然后根据操作的结果发送响应邮件 我正在寻找一种为此应用程序编写测试的方法 理想情况下 我希望这些测试能够启动自己的邮件服务器 将我的测试电子邮件推送到该邮件服
  • 如何等待 Angular Google 地图将 getGMap 附加到控制对象

    我一直在尝试在google maps Map由创建的对象ui gmap google map指令来自Angular 谷歌地图库 我需要动态地执行此操作 因此 至少通过我的简短测试 似乎使用events上的参数ui gmap google m
  • ccAvenue 支付网关中 ios 9 中的安全错误

    在发布 iOS 9 之前 我将 ccAvenue paymeny 网关集成到我的 iOS 应用程序中 付款已成功转移到 iOS 8 中的商家帐户 当我在 iOS 9 中测试我的应用程序时 付款已转移到商家帐户 但显示安全错误 我也改变lib
  • 函数的返回类型是重整名称的一部分吗?

    假设我有两个具有相同参数类型和名称的函数 不在同一个程序中 std string foo int x return hello int foo int x return x 编译后它们会具有相同的损坏名称吗 返回类型是 C 中重整名称的一部