在C++中,由于重载等技术的存在,编译器要将函数、结构体、类等等的信息传递给链接器,就不能像C语言那样简单地通过函数名来完成,它需要提供额外的参数信息,而还要和C语言共用链接器,这就需要用到名字改编(name mangling),又叫名字修饰(name decoration)。

名字改编也罢,但由于历史原因,C++没有这方面的标准(C++没有ABI方面的标准,名字改编只是ABI问题的一部分)。于是编译器们各自为政,生成的文件无法通用。

于是:在Windows下,你会发现,同一版本的QtCore4.dll,不同编译器编译出来的无法通用。同一个函数void f(std::wstring s),同一个编译器(MSVC),不同选项(/Zc:wchar_t-/Zc:wchar_t),导出的符号不同。

在Qt中,我们只关注下面两种名字改编:

  • Itanium C++ ABI (GCC3、GCC4,包括MinGW)
  • Microsoft C++ ABI

注:对于Intel编译器,在Windows下和微软ABI一致,在其他平台下和GCC保持一致。

用例子来说话

找个什么例子呢?额... 不妨找个简单的动态库,看看它导出的函数名字吧。Qt的Core和Gui模块都太复杂了,就拿Qt的Test模块来看看吧,QtTest4.dll 或 libQtTest.so.4.8.0

如何看到符号呢?

  • 在windows下,我们可以使用 dumpbin 工具:
dumpbin /EXPORTS qttest4.dll
  • 在linux,我们可以使用 nm 或 readelf 工具:
nm -D libQtTest.so.4.8.0
readelf -Ws libQtTest.so.4.8.0

准备工作完毕,你运行上述命令,即可看到大量的符号出现在屏幕上,我们下面对比Qt Manual给出的函数,看看这些符号(只简单看几个,不然我也看不懂)

放一行太长了,只好这样了,原型/Itanium/Microsoft

1

void QTest::qSleep(int ms)

原型

_ZN5QTest6qSleepEi

Itanium ABI

?qSleep@QTest@@YAXH@Z

Microsoft ABI

2

const char * QTest::currentTestFunction()

 

_ZN5QTest19currentTestFunctionEv

 

?currentTestFunction@QTest@@YAPBDXZ

 

3

int QTest::qExec(QObject *testObject, int argc=0, char **argv=0)

 

_ZN5QTest5qExecEP7QObjectiPPc

 

?qExec@QTest@@YAHPAVQObject@@HPAPAD@Z

 

4

int QTest::qExec(QObject *testObject, const QStringList &arguments)

 

_ZN5QTest5qExecEP7QObjectRK11QStringList

 

?qExec@QTest@@YAHPAVQObject@@ABVQStringList@@@Z

 

5

QTestData & QTest::newRow(const char * dataTag)

 

_ZN5QTest6newRowEPKc

 

?newRow@QTest@@YAAAVQTestData@@PBD@Z

 

6

...

 

...

 

...

 

这堆东西,乱七八糟的,怎么看啊??

试着读读看

void QTest::qSleep(int ms)

原型

_ZN5QTest6qSleepEi

Itanium ABI

?qSleep@QTest@@YAXH@Z

Microsoft ABI

Itanium

_ZN5QTest6qSleepEi

加几个空格

_Z N 5 QTest 6 qSleep E i

_Z

 

C++名字前缀

N...E

复合名字起始字符 QTest::qSleep

 

5 QTest

长度为5的名字QTest

6 qSleep

长度为6的名字qSleep

i

 

参数类型 int

Microsoft

?qSleep@QTest@@YAXH@Z

这个信息有些多,有些乱,比前面的风格差远了。而且很多过时的东西都混在其中。

C++名字前缀

qSleep

最内层的名字

@

名字分隔符

QTest

前一个名字的外层名字

@@

名字结束

Y

函数调用是 near 方式

A

调用惯例__cdecl

X

返回值类型 void

H

参数类型 int

@

参数表结束

Z

表示这是一个函数

关于这些东西的解释,详见calling_conventions

参考

C++ ABI之名字改编(以Qt为例)的更多相关文章

  1. C++ ABI之名字改变,编译器生成符号研究(以Qt为例)

    在C++中,由于重载等技术的存在,编译器要将函数.结构体.类等等的信息传递给链接器,就不能像C语言那样简单地通过函数名来完成,它需要提供额外的参数信息,而还要和C语言共用链接器,这就需要用到名字改编( ...

  2. 以QT为例谈环境搭建

    以QT为例谈环境搭建 作者:哲思 时间:2022.1.5 邮箱:1464445232@qq.com GitHub:zhe-si (哲思) (github.com) 前言 自从实习结束,好久没写博客了. ...

  3. Qt编程之Qt样例表(QSS)

    For a long time, Qt has allowed you to decorate your GUIs with CSS’ish style sheets. Inspired by the ...

  4. C++的二进制兼容问题(以QT为例)

    二进制不兼容带来的问题(需要重新编译库文件,以前编译的失效): http://my.oschina.net/lieefu/blog/505363?fromerr=f5jn7rct 二进制不兼容的原理: ...

  5. qt 单例程序

    1.http://qt.nokia.com的网站把QtSingleApplication 的源代码qtsingleapplication-2.6_1-opensource.zip 下载下来,然后解压缩 ...

  6. wchar_t是内置还是别名(亲测有效:wchar_t在windows下是16位整数的别名,在linux等平台下是32位整数的别名。MSVC2008开始默认是/Zc:wchar_t)

    接前一篇C++ ABI之名字改编(以Qt为例),继续看看C++名字改编相关的问题. 问题 MSVC 有一对选项/Zc:wchar_t- 与 /Zc:wchar_t控制wchar_t 于是 wchar_ ...

  7. C++中的名字重整技术

    C++ 一直为人诟病之一的原因是他的二进制模块兼容性不好,即ABI(Application Binary Interface)问题.对于同一源代码,不同编译器,甚至同一编译器不同版本都不兼容,其编译出 ...

  8. qt creator源码全方面分析(2-1-1)

    目录 C++的策略/二进制兼容性问题 定义 ABI注意事项 可做与不可做 库程序员的技巧 位标志 使用d指针 故障排除 在没有d指针的情况下将新数据成员添加到类中 添加已重新实现的虚函数 使用新类 向 ...

  9. 自定义的插件如何加载到Qt Designer中(详细)

    要想在Qt Designer中使用自定义控件,必须要使Qt Designer能够知道我们的自定义控件的存在.有两种方法可以把新自定义控件的信息通知给Qt Designer:“升级(promotion) ...

随机推荐

  1. linux MySQL 5.7+keepalived 主备服务器自主切换

    一.环境准备1.关闭防火墙与selinux systemctl stop firewalld setenforce 0 sed -i 's/SELINUX=.*/SELINUX=disabled/g' ...

  2. Linux 学习笔记 2 Centos 安装与网络的配置以及VI编辑器的使用

    前言 当然,还是觉得Centos 在众多的Linux 发行版中,还是很有地位的,好多的服务器大多沿用的都是一代的Centos 因为它开源(这是废话)而且稳定,这才是服务器沿用的最重要的一项指标. 镜像 ...

  3. 「HDU3823」 Prime Friend 解题报告

    Prime Friend Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...

  4. 1069 微博转发抽奖 (20分)C语言

    小明 PAT 考了满分,高兴之余决定发起微博转发抽奖活动,从转发的网友中按顺序每隔 N 个人就发出一个红包.请你编写程序帮助他确定中奖名单. 输入格式: 输入第一行给出三个正整数 M(≤ 1000). ...

  5. spring之整合Hibernate

    spring整合Hibernate整合什么? 1.让IOC容器来管理Hibernate的SessionFactory. 2.让Hibernate使用上spring的声明式事务. 整合步骤: 1.加入H ...

  6. Hyperledger Fabric1.4 安装

    Hyperledger Fabric 依赖的软件版本查看官方 github 地址 https://github.com/hyperledger/fabric 下文件 /docs/source/prer ...

  7. luogu 题解 P2380 【狗哥采矿】

    拿到dp题我们就要想如何推方程 “最北边有bloggium的收集站,最西边有 yeyenum 的收集站.现在要你在这些格子上面安装向北或者向西的传送带(每个格子只能装一种).” 这说明了什么,对于某一 ...

  8. Date类与日期格式

    Date类概述: 表示特定的瞬间,精确到毫秒. Date()分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒).Date(long date)分配 Date 对象并初始化此对象,以表 ...

  9. Docker系列-第七篇Docker构建SpringBoot应用

    1.基于Dockerfile构建SpringBoot镜像 1.1准备工作 将SpringBoot项目通过maven打成jar包 mvn clean package #使用maven打包项目 1.2使用 ...

  10. Tarjan算法伪代码

    伪代码: 栈:当前dfs路径上的点low[x]:x能到达的点中最小的dfn dfs(x,t)    将x入栈     dfn[x]=t    low[x]=t    for(x,y)        i ...