标签: abi

优化标签(空结构)函数参数的处理

在某些情况下,我们使用标签来区分函数。标签通常是一个空结构:

struct Tag { };
Run Code Online (Sandbox Code Playgroud)

假设我有一个使用此标签的函数:

void func(Tag, int a);
Run Code Online (Sandbox Code Playgroud)

现在,我们调用这个函数:

func(Tag(), 42);
Run Code Online (Sandbox Code Playgroud)

并检查生成的 x86-64 反汇编,godbolt

mov     edi, 42
jmp     func(Tag, int)            # TAILCALL
Run Code Online (Sandbox Code Playgroud)

没关系,标签得到了完全优化:没有为其分配寄存器/堆栈空间。

但是,如果我查看其他平台,就会发现该标签存在一些。

在 ARM 上,r0用作标签,并且它被归零(似乎没有必要):

mov     r1, #42
mov     r0, #0
b       func(Tag, int)
Run Code Online (Sandbox Code Playgroud)

对于 MSVC,ecx被用作标记,并且它是从堆栈中“初始化”的(同样,似乎没有必要):

movzx   ecx, BYTE PTR $T1[rsp]
mov     edx, 42                             ; 0000002aH
jmp     void func(Tag,int)                 ; func
Run Code Online (Sandbox Code Playgroud)

我的问题是:是否有一种标签技术在所有这些平台上都得到了同样的优化?


注意:我没有找到 SysV ABI 指定可以在参数传递时优化空类的地方...(甚至,Itanium C++ ABI说:“空类的传递与普通类没有什么不同”。)

c++ arm x86-64 abi calling-convention

6
推荐指数
1
解决办法
845
查看次数

超大结构如何返回到堆栈上?

据说从函数返回过大的值(而不是返回指向 的指针)会在堆栈上产生不必要的复制我所说的“超大”是指无法放入返回寄存器的值。structstructstruct

不过,引用维基百科

当需要超大的结构返回时,另一个指向调用者提供的空间的指针将作为第一个参数添加到前面,将所有其他参数向右移动一个位置。

返回结构/类时,调用代码分配空间并通过堆栈上的隐藏参数传递指向该空间的指针。被调用函数将返回值写入该地址。

看起来至少在x86架构上,所讨论struct的问题是由被调用者直接写入调用者指定的内存中,那么为什么会有一个副本呢?返回超大的structs 真的会在堆栈上产生副本吗?

c x86 struct abi calling-convention

6
推荐指数
2
解决办法
1172
查看次数

使用 C++ 代码的 C 包装器来实现 ABI 稳定性?

Jason Turner在他的演讲中提议打破 C++ ABI 以保持该语言的发展。他还提到,如果出于兼容性原因需要,可以通过将 C++ 库包装到 C 库中来隔离 C++ ABI 更改。

27:30相关截图:

C 包装图

这里“BinaryLibrary”和“Old C++ stdlib”使用旧的 ABI,“NewExecutable”使用假设的更新 ABI。

据我了解,这是有效的,因为“BinaryLibrary”的旧 C++ ABI 被烘焙成具有更稳定接口的单独二进制文件。

但是什么让 C 成为一个好的替代方案呢?难道它的ABI也不能改变吗?

c c++ abi

6
推荐指数
1
解决办法
781
查看次数

Win32 宽字符串对齐要求

我将 GUI 代码中的问题缩小到SetWindowTextW(HWND, wchar_t *)如果新窗口标题未与两个字节对齐则默默失败。在本例中,SetWindowText()返回1( success ) 但不设置新文本。

\n

MSVC 上的自然对齐wchar_t是 2 个字节,所以这绝对是我的错误。但为了确保我尝试找到 Win32 字符串的对齐规则。

\n

我没有找到官方文档,只是一个旧的新闻组帖子提到了 Open Watcom 编译器\xc2\xa0\xe2\x80\x93的错误报告,该报告声称Windows NT 上的 Win32 和 COM 实际上需要4 字节对齐!虽然这对我来说似乎很奇怪,但我注意到 MSVC 确实将每个wchar_t文字对齐到四个字节,而不是两个。实际上,您可以wchar_t通过 使 MSVC 更密集地打包常量字符串alignas(2)。Win32 中的堆粒度也 >=8 字节。

\n

如果 Win32 需要对宽字符字符串进行四字节对齐(如源声明),并且 API 调用在错误的数据对齐上默默失败(如SetWindowText()1 字节对齐),我感觉遇到了很大的麻烦。

\n

有没有官方文档说明 Win32/COM 中宽字符串的明确对齐要求?是两个字节还是四个字节?

\n
\n

重现问题的代码:

\n
#include <Windows.h>\n#include <CommCtrl.h>\n#include <cassert>\n\nint main() {\n\n  auto …
Run Code Online (Sandbox Code Playgroud)

c++ winapi abi memory-alignment

6
推荐指数
1
解决办法
294
查看次数

Android NDK - 链接外部库的问题(找不到它)

我在cygwin下使用Android NDK r6b(系统正确更新).我正在修改hello-jni示例以学习使用NDK.因为我有一个用C++编写的库,我希望在hello-jni中使用(实际上,我创建了一个名为helloworld的prj,其中包含一个名为ndkfoo.cpp的.cpp文件),我在Eclipse中创建了一个新的Android项目(更新为Android),添加了一个jni目录,添加了一个Android.mk和Application.mk文件,编辑它们以编译.cpp.在编译结束时,我获得了一个.so文件.

现在,在helloworld Android.mk中,我需要进行一些编辑,以告诉链接器包含该库.假设库文件是libmylib.so,我有以下android.mk脚本:

LOCAL_PATH:= $(调用my-dir)

包括$(CLEAR_VARS)

LOCAL_MODULE:= ndkfoo

LOCAL_SRC_FILES:= ndkfoo.cpp

LOCAL_C_INCLUDES + = $(LOCAL_PATH)/ mylib

LOCAL_LDLIBS + = -L $(LOCAL_PATH)/../../ mylib/libs/armeabi/-lmylib

包含$(BUILD_SHARED_LIBRARY)

我的目录按以下方式组织:

d:/android/android-ndk-r6b => android ndk root
d:/android/workspace/helloworld => helloworld project
d:/android/workspace/mylib => mylib project library
Run Code Online (Sandbox Code Playgroud)

(因此,libmylib.so的路径是:d:/ android/workspace/mylib/libs/armeabi).

不幸的是,这似乎不起作用.如果我从ndkfoo.cpp 删除对mylib的每个引用,它甚至在我的手机上编译并运行.如果我不删除对mylib的引用,它会编译但不会链接:我得到以下结果:

D:/android/android-ndk-r6b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windo ws/bin /../ lib/gcc/arm-linux-androideabi/4.4.3 /../ ../../../arm-linux-androideabi/ bin/ld.exe:找不到-lmylib

PS.我忘了提到我在helloworld项目的jni目录下运行ndk-buld.PSS的.我在互联网上发现了很多类似的问题.我一直使用Visual C/C++ IDE,所以我对GCC,makefile等都很新...

abi linker-errors android-ndk

5
推荐指数
1
解决办法
1万
查看次数

如何指示编译器为虚函数生成别名?

有关背景,请参阅此问题.

基本上,我有一个类的以下定义

class  MyClass {
    virtual int foo4(double, int);
};
Run Code Online (Sandbox Code Playgroud)

有没有办法指示编译器生成两个可以解析的符号foo4?也就是说,如果可执行文件要求动态链接器解析_ZN7MyClass4foo4Edi(符号for MyClass::foo4(double, int))和其他一些符号(比方说_ZN7MyClass9reserved1Ev,符号MyClass::reserved1()),我希望动态链接器将两者解析为&MyClass::foo4(double, int).我在Linux上使用相当现代的GCC.

c++ linux virtual linker abi

5
推荐指数
1
解决办法
394
查看次数

如何编写跨版本/平台的Linux内核模块?

我是编程Linux内核模块的新手,许多关于该主题的入门指南包含很少有关如何构建内核模块的信息,该内核模块将在Linux的许多版本和CPU平台上运行.我见过的大多数指南都只是说"Linux不能确保版本之间的任何 ABI/API兼容性".但是,其他操作系统确实为主要版本提供了这些保证,并且指南主要针对2.7(现在有点旧).

我想知道现在是否有任何类型的ABI/API兼容性,或者是否有任何标准方法来处理版本控制,而不是将我的代码的内核相关位隔离到具有大量预处理器指令的文件中.(另外,在第二种情况下我应该使用任何标准的预处理器符号吗?)

abi kernel-module linux-device-driver linux-kernel

5
推荐指数
2
解决办法
1354
查看次数

C++代码可以与其他C++代码可靠地交互吗?

在C中,我习惯于编写一个可以从任何客户端代码调用的共享库,只需链接库并包含相关的头文件即可使用它.但是,我已经读过C++的ABI过于易变,非标准,无法从其他来源可靠地调用函数.

这将使我相信在C++中创建像C一样通用的真正共享库是不可能的,但现实世界的实现似乎表明不是这样.例如,Node.js公开了一个非常简单的模块系统,它允许使用该函数动态导出普通的C++函数(不extern "C").NODE_SET_METHOD

C++ API的哪些元素可以安全公开(如果有的话),以及允许C++代码与其他C++代码交互的常用方法是什么?是否可以创建可以公开C++类的共享库?或者由于ABI不一致,是否必须为每个程序单独重新编译这些类?

c++ shared-libraries abi

5
推荐指数
1
解决办法
216
查看次数

使用C++ 11与GCC 4.8默认导致链接错误与私有继承和提升

前言

使用我目前无法分解为MCVE的大量代码,所以我会尽我所能.


问题

我正在使用一个编译为静态库的大型项目libfoo.a.一个单独的项目,bar链接到该库."冒犯"片段libfoo如下:

class Base {
public:
    void foo(){}
    void bar(){}
};

class Derived : private Base {
public:
    using Base::foo;
};
Run Code Online (Sandbox Code Playgroud)

双方libfoobar广泛使用的.bar必须编译,-std=c++11因为它使用了C++ 11的功能,但libfoo可以用最少的选项编译(即GCC v4.8使用的默认编译器选项,似乎是).-std=c++0x -std=gnu++03

当我尝试bar使用编译的GCC默认值进行链接时,它会因为冗长的名称错误警告而失败,该警告会减少为:-std=c++0x libfoo.a

Undefined reference to Base::Derived::foo()
Run Code Online (Sandbox Code Playgroud)

当我重新构建libfoo.a-std=c++11,不再出现此问题.


工作到目前为止

我比较了libfoo.avia 的输出,在这两种情况下,都存在适当的符号.我还浏览了Cxx11Abi兼容性文档,看来这个编译器设置不应该"破坏"兼容性.


这个链接器问题的原因是什么?

c++ linux gcc abi c++11

5
推荐指数
1
解决办法
301
查看次数

为什么System V/AMD64 ABI要求16字节堆栈对齐?

我读过的,因为它是为"业绩原因"做不同的地方,但我仍然不知道什么是在性能得到这个16字节对齐提高了特殊情况.或者,无论如何,选择这个的原因是什么.

编辑:我想我以误导的方式写了这个问题.我没有询问为什么处理器使用16字节对齐的内存更快地处理事情,这在文档中随处可见.我想要知道的是,强制执行16字节对齐比仅让程序员在需要时自己对齐堆栈更好.我问这个是因为根据我的汇编经验,堆栈实施有两个问题:只有少于1%的执行代码才有用(所以其他99%实际上是开销); 它也是一个非常常见的错误来源.所以我想知道它最终是如何得到回报的.虽然我对此仍有疑问,但我接受了彼得的回答,因为它包含了我原来问题的最详细答案.

assembly x86-64 abi

5
推荐指数
1
解决办法
1144
查看次数