C++ ABI 提供了什么

前面关于 type_info 的讨论我们认识到一个语言的实现可以有多种可能,这个语言的标准往往只把一些公有的 interface 展现给这个语言的程序员。但实际上,很多时候我们可能需要更加底层的信息来帮助我们完成或者理解这个语言的实现,它往往在这个 ABI 层次上提供了相关的文档。我们这里参看这个文档。这里选择了一些有意思的东西

数据布局

成员指针(member pointer)实际的表示是 ptrdiff_t(指针偏移,我们在计算 any_ptr 的转换的时候也使用了这个类型),因此它的空一般使用 -1。而成员函数指针(pointer to member function)是两部分组成的,ptr 部分是函数指针(对于 virtual function 来说是 1+ vtab offset,也是使用 ptrdiff_t 表示的),使用 0 表示空,adj 表示相对于 this 的偏移(ptrdiff_t)。之所以需要 adj 这个部分也是为了支持多继承。

使用 new 产生一个 array 的时候需要存放这个 array 的大小(除非 T 具有 trivial 的 destructor 或者使用的是 ::operator new[](size_t, void*)),这称为 cookie,这一般存放在申请的内存最开始。

每个 function scope 的 static variable 存在所谓的 initialization guard variable,这就是为什么可以通过 lambda 初始化 static variable 同时能够处理多线程的情况的原因。这占用 64 bits,其中第一个字节表示初始化的状态。

在 vtab 里面会存放 type_info 对象的指针,通常是嵌入在对象的 virtual pointer 的值 -1;而在 -2 位置存放的是 virtual pointer 相对于这个类型的对象的偏移量。这主要是应对 virtual base 的情形,这个时候对象可能存在多个 virtual pointer,而这个偏移量对应的自然是 primary vtab。

函数调用

pass-by-value 对于 non-trivial copy constructor 对象来说实际的实现其实是通过 copy constructor 生成一个临时对象,然后 pass by reference。而 pass-by-reference 实际上是 pass-by-pointer 而在语言层面上翻译成为 reference。返回对象的过程一般是 caller 分配存放该对象的空间,然后将 this 指针传递给 callee(作为第一个隐式传递的参数),而 callee 创建这个对象。实际在实现这个函数的时候,我们其实无法看见这个指针,因此在函数里会有另一个变量 hold 这个返回值,在返回这个对象的时候发生 copy constructor/move constructor。

这个地方有意思的大概是 Google 的 style guide 要求把返回值尽量使用 non-const pointer 传递到函数里,其实是显式的要求程序员做和编译器一样的事。

构造函数其实返回值永远是 void 所以不需要写出来。

编译单元可以使用 #pragma priority 将目标文件中注入一个 struct 描述其构造顺序,通过 __cxa_priority_init 在运行时访问。这些初始化后的静态变量将在 __cxa_atexit 和 __cxa_finalize 时(后者调用前者)释放,用户通过 atexit 实际上也是注册 __cxa_atexit。

异常处理

这个分为两种:

  • throw/catch 类型,抛出点并不知道哪里会处理,这对应 __Unwind_RaiseException
  • longjmp 类型,跳出时其实是知道跳到哪里,使用 __Unwind_ForcedUnwind

在 unwind 过程里面,通常会有两个 phase,每个 phase 都会调用对应的 personality routine,但是传递的参数对应的是 phase,其行为也不一样

  • search phase,从栈顶开始一个 frame 一个 frame 的寻找能够接受 exception 的 frame,如果一直都没有,最终会调用 terminate
  • cleanup phase,一样的顺序,这个过程中调用 cleanup code 释放每个 frame 里面需要处理的对象

异常本身是 language 与 implementation dependent 的,但是通常会存放一个 header,这通过 abi layer 的函数使用。

Advertisements
C++ ABI 提供了什么

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s