问题标签 [abi]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c - 在 C 中按值传递结构而不是传递指针有什么缺点吗?
在 C 中按值传递结构而不是传递指针有什么缺点吗?
如果结构很大,显然存在复制大量数据的性能方面,但对于较小的结构,它应该基本上与向函数传递多个值相同。
当用作返回值时,它可能会更有趣。C 只有函数的单个返回值,但您通常需要多个。所以一个简单的解决方案是将它们放在一个结构中并返回它。
是否有任何理由支持或反对这一点?
由于我在这里谈论的内容对每个人来说可能并不明显,所以我将举一个简单的例子。
如果您使用 C 进行编程,您迟早会开始编写如下所示的函数:
这不是问题。唯一的问题是您必须与您的同事商定参数的顺序,以便您在所有函数中使用相同的约定。
但是当你想返回相同类型的信息时会发生什么?你通常会得到这样的东西:
这工作正常,但问题更多。返回值是返回值,但在此实现中不是。从上面无法看出函数 get_data 不允许查看 len 指向的内容。并且没有什么可以让编译器检查一个值是否实际上是通过该指针返回的。所以下个月,当其他人在没有正确理解的情况下修改代码(因为他没有阅读文档?)它会在没有人注意到的情况下被破坏,或者它开始随机崩溃。
所以,我提出的解决方案是简单的结构
示例可以这样重写:
出于某种原因,我认为大多数人会本能地让 Exam_data 获取指向结构 blob 的指针,但我不明白为什么。它仍然得到一个指针和一个整数,它们在一起更清楚了。而在 get_data 的情况下,不可能像我之前描述的那样搞砸,因为长度没有输入值,并且必须有一个返回的长度。
macos - 为什么 Mac ABI 要求 x86-32 的 16 字节堆栈对齐?
我可以理解旧 PPC RISC 系统甚至 x86-64 的这一要求,但对于久经考验的旧 x86?在这种情况下,堆栈只需要在 4 字节边界上对齐。是的,一些 MMX/SSE 指令需要 16 字节对齐,但如果这是被调用者的要求,那么它应该确保对齐正确。为什么要让每个调用者都负担这个额外的要求?这实际上会导致性能下降,因为每个呼叫站点都必须管理此要求。我错过了什么吗?
更新:在对此进行了更多调查并咨询了一些内部同事之后,我对此有一些理论:
- 操作系统的 PPC、x86 和 x64 版本之间的一致性
- 似乎 GCC 代码生成器现在始终执行 sub esp,xxx 然后将数据“移动”到堆栈上,而不是简单地执行“推送”指令。这实际上在某些硬件上可能更快。
- 虽然这确实使调用站点有点复杂,但在使用调用者清理堆栈的默认“cdecl”约定时几乎没有额外的开销。
我对最后一项的问题是,对于依赖于被调用方清理堆栈的调用约定,上述要求确实“丑化”了代码生成。例如,某些编译器决定实现更快的基于寄存器的调用样式以供其内部使用(即任何不打算从其他语言或源调用的代码)?这种堆栈对齐的事情可能会抵消通过在寄存器中传递一些参数所获得的一些性能提升。
更新:到目前为止,唯一真正的答案是一致性,但对我来说,这有点太容易了。我在 x86 架构方面拥有超过 20 年的经验,如果一致性,而不是性能或其他具体的东西,真的是原因,那么我恭敬地建议开发人员要求它有点天真。他们忽略了近三年的工具和支持。特别是如果他们希望工具供应商能够快速轻松地为他们的平台调整他们的工具(也许不是......它是苹果......),而不必跳过几个看似不必要的障碍。
我会在另一天左右给出这个话题然后关闭它......
有关的
assembly - 大多数现代系统中堆栈增长的方向是什么?
我正在准备一些 C 语言培训材料,我希望我的示例适合典型的堆栈模型。
C 堆栈在 Linux、Windows、Mac OSX(PPC 和 x86)、Solaris 和最新的 Unix 中的发展方向是什么?
linux - 为什么我需要在 linux 内核升级后重新编译 vmware 内核模块?
linux 内核升级后,我的 VMWare 服务器无法启动,直到使用 vmware-config.pl 进行一些重新配置工作(包括构建一些内核模块)。
如果我用最新的 Windows Service Pack 更新我的 Windows VMWare 主机,我通常不需要做任何事情来运行 VMWare。
为什么 VMWare 在 Linux 和 Windows 之间的工作方式不同?此重新编译操作是否在 Linux 平台上比 Windows 带来任何好处?
c++ - 使用 Boost 创建具有向后兼容 ABI 的库
我正在研究某个 C++ 库(或更多框架)。我想让它向后兼容以前的版本,不仅保留 API 兼容性,还保留 ABI(就像 Qt 所做的出色工作一样)。
我使用了 Boost 的许多功能,在我看来,这使得向后兼容变得不可能,除非我强迫用户拥有完全相同(有时是旧的)版本的 Boost。
有没有办法(不重写 Boost 的 1/2)在其命名空间周围制作一些“前缀”/重命名它以防止它干扰用户版本的 Boost?
例如我的 libXYZ 使用 Boost 1.33 并且它有 class boost::foo
. 在 1.35 版本boost::foo
中升级并添加了新成员,因此,boost::foo
从 1.33 和 1.35 开始不兼容 ABI。因此,libXYZ 的用户必须使用 Boost 1.33 或使用 Boost 1.35 重新编译 libXYZ(这可能已经以 XYZ 无法编译的方式破坏了某些 API)。
注意:我说的是带有 ELF 的 UNIX/Linux 操作系统,其中动态链接类似于静态链接,因此您不能链接两个不同版本的库,因为符号会干扰。
我可能想到的一种合适的解决方案是将 Boost 放在其他一些私有名称空间中。因此,libXYZ 将使用::XYZ::boost::foo
而不是::boost::foo
. 这将防止与用户可能使用的其他版本的 Boost 发生冲突。
因此,libXYZ 将继续与 Boost 1.33 一起工作,静态或动态链接到它与其他命名空间,假设它:
- 不会在外部公开 Boost API。
- 将保持公开 API 的稳定私有版本。
有没有办法用Boost做这样的事情?
编辑:最后我决定创建一个脚本,将源中的所有 boost 符号重命名为一些自定义符号。
基本原理:简化构建过程,独立于编译器可见性支持,而且它的可见性仅适用于动态库,对于静态这不起作用,所以我需要为每种类型的库单独构建和依赖。
该脚本在那里可用: http: //art-blog.no-ip.info/files/rename.py
编辑 2: Boost BCP 的最新版本支持命名空间重命名。
windows - C 运行时对象,dll 边界
为 dll 设计 C API 的最佳方法是处理传递依赖于 C 运行时的“对象”(文件 *、malloc 返回的指针等)的问题。例如,如果两个 dll 与不同版本的运行时链接,我的理解是您无法将 FILE* 从一个 dll 安全地传递给另一个。
是使用依赖于 Windows 的 API(保证跨 dll 工作)的唯一解决方案吗?C API 已经存在并且很成熟,但主要是从 unix POV 设计的(当然,仍然必须在 unix 上工作)。
c++ - 如何在 DLL 边界上公开 STL 列表?
我有一个 DLL,它需要访问存储在主机应用程序的 STL 容器中的数据。因为 C++ 没有标准的 ABI,而且我想支持不同的编译器,所以应用程序和 DLL 之间的接口基本上必须保持纯旧数据。
对于向量,这相对简单。您可以简单地返回向量的内存块,因为它保证是连续的:
现在,DLL 可以通过该接口对向量数据进行安全的只读访问。DLL 也可以包装它以将内容复制到自己的向量中。
但是 STL 列表(和双端队列)呢?是否有另一种直接的方法允许通过 DLL 边界进行访问?还是我必须求助于某种 GetFirst()/GetNext() 接口?我可能需要对很多列表执行此操作,因此最好有一个像矢量这样简单的解决方案。
performance - 为什么数据结构对齐对性能很重要?
有人可以给我一个简短而合理的解释,解释为什么编译器会向数据结构添加填充以对齐其成员吗?我知道这样做是为了让 CPU 可以更有效地访问数据,但我不明白为什么会这样。
如果这只是 CPU 相关的,为什么在 Linux 中对齐双 4 字节而在 Windows 中对齐 8 字节?
linux - 为什么共享库的 ELF 标头会将 Linux 指定为 OSABI?
我的 Linux 系统 (Fedora 9) 上的所有标准共享库都将 ELFOSABI_NONE (0) 指定为它们的 OSABI。
这很好 - 但是我从供应商那里收到了一个共享库,其中 ELF 标头中给出的 OSABI 是 ELFSABI_LINUX (3)。
对于用于 Linux 系统的共享库来说,这听起来并不是一个不合理的值,但是它与我所有其他库的值不同 - 所以当我尝试使用 dlopen() 从一个在我的其他库中,这失败并出现错误“ELF 文件操作系统 ABI 无效”。
我编译了 FreeBSD 实用程序brandelf.c并使用它将 OSABI 类型更改为 0,现在该库似乎可以与其他所有内容一起使用。
我只是想知道 - 为什么你认为这个库被标记为 ELFOSABI_LINUX?我猜也许他们在另一个系统上交叉编译并指定了一些 gcc 标志,导致这个值被设置到 ELF 标头中?我试图实现类似但无法确定适当的 gcc 标志或标志。
我想知道可能的原因是什么,因为这个特定的供应商在没有很多手的情况下不会做任何事情,我想说“你可能正在做 X,但这意味着我们必须修改你的库在我们收到它们之后”。
c++ - 为什么应用程序二进制接口对编程很重要
我不明白为什么 ABI 是开发用户空间应用程序的重要上下文。操作系统的系统调用集是否被视为 ABI?但如果是这样,那么关于系统调用的所有复杂性不都封装在标准库中吗?
那么ABI 兼容性是否仅与在不同平台上运行静态链接的应用程序相关,因为系统调用将嵌入到二进制文件中?