首页 > 解决方案 > c++ 中的静态库如何与 name mangle 一起使用?

问题描述

我要求理解,在 c 中没有名称修饰,但 c++ 有。这是如何工作的,例如说我有以下文件

文件 exlib.hpp

#ifndef EXLIB
#define EXLIB

#include <iostream>

int sum(int, int);
int sum(int, int, int);
int sum(int, int, int, int);

#endif

文件 exlib.cpp

#include "exlib.hpp"

int sum(int a, int b)
{
    std::cout << "In sum(int, int)" << std::endl;
    return a + b;
}

int sum(int a, int b, int c)
{
    std::cout << "In sum(int, int, int)" << std::endl;
    return a + b + c;
}

int sum(int a, int b, int c, int d)
{
    std::cout << "In sum(int, int, int, int)" << std::endl;
    return a + b + c + d;
}

文件 exapp.cpp

#include "iostream"
#include "exlib.hpp"

int main()
{
    std::cout << "Sum = " << sum(1, 1) << std::endl;
    std::cout << "Sum = " << sum(2, 2, 2) << std::endl;
    std::cout << "Sum = " << sum(3, 3, 3, 3) << std::endl;
}

编译

$ g++ -c exlib.cpp
$ g++ exapp.cpp exlib.o -o exapp
$ ./exapp

exlib.o 中的总和名称是否错误?

输出:

Sum = In sum(int, int)
2
Sum = In sum(int, int, int)
6
Sum = In sum(int, int, int, int)
12
  1. 在 main 中的 name mangle 之后如何正确调用 sum ?,对于 name mangling 有任何规则,即在 main 中替换相同的名称或它们如何识别?
  2. 所有编程语言都以相同的方式命名?

谢谢。

标签: c++name-mangling

解决方案


虽然 C++ 提供了多态性(即,不同的事物可以在同一范围内通过使用其他特性来区分它们而被命名为相等),但链接器不支持这一点(无论是静态链接还是动态链接)。因此,C++ 编译器使用名称修饰。(其他功能用于装饰原始标识符以产生唯一名称。)

C++ 编译器自己编译每个 C++ 文件(又名翻译单元)。因此,很明显,名称修改必须由该编译器以独特的、可重现的方式完成。即相同的声明必须始终映射到相同的符号。否则,链接器将无法解析(仅)在一个文件中声明并在另一个文件中定义的符号。

但是,没有通用的名称修饰标准(例如,作为 C++ 标准的一部分)。

因此,即使在同一平台上,两个不同编译器生成的二进制代码也可能由于不同的名称修饰(以及其他细节)而不兼容。(对于MS Visual C++,这甚至会导致来自不同版本的二进制文件不兼容。)

为了克服这个问题,存在用于某些平台(例如 Linux)的应用程序二进制接口(ABI)。ABI 的一个细节是标准化的名称修饰。


推荐阅读