1: void f(mystruct *a)
2: void f(const mystruct *a)
Run Code Online (Sandbox Code Playgroud)
更改1-> 2的函数签名是否会破坏C中的API/ABI?
如何改变2-> 1?
我正在Windows上学习x64汇编以获得"有趣".Windows上x64调用约定的MSDN文档说:
调用者负责为被调用者分配参数空间,并且必须始终为4个寄存器参数分配足够的空间,即使被调用者没有那么多参数也是如此.这有助于简化支持C非原型函数和vararg C/C++函数.
由于我的功能是不是C unprototyped函数或可变参数的C/C++函数,这是否意味着我可以一直使用[rsp+8]到[rsp+32](假设未修改的价值rsp我的函数中调用后右)通用存储,如为局部变量?
现在的问题是相对简单的:我怎样才能建立4.x版系列的GCC(连同的binutils和朋友),关于相同的架构主机编译器的目标2.4 ABI?
主机系统将是x86或x86_64,唯一的要求是只要ABI匹配,构建的ELF文件就在旧内核上运行.(存在内核源/头)
为了将其链接,也需要兼容的libc.但是,我也可以动态链接它,因为我知道(g)libc版本.
任何指针都将非常感激.我对crosstool-ng有点熟悉,但这似乎不再支持2.4内核了(出于显而易见的原因).
可以安全地假设在任何实际可用的平台ABI中定义了哪些项目?
的价值 CHAR_BIT
尺寸,对齐要求和对象表示:
void*,size_t,ptrdiff_tunsigned char 和 signed charintptr_t 和 uintptr_tfloat,double和long doubleshort 和 long longint和long(但在这里,我希望"不")空对象指针的对象表示
空函数指针的对象表示
例如,如果我有一个库(由未知但符合ABI的编译器编译)发布此函数:
void* foo(void *bar, size_t baz, void* (*qux)());
Run Code Online (Sandbox Code Playgroud)
我可以假设能够在我的程序中安全地调用它,无论我使用哪个编译器?
或者,反过来说,如果我正在编写一个库,是否有一组类型,如果我将库的公共接口限制为此集,它将保证在它构建的所有平台上都可用?
我已经下载了一个在GCC中ABI更改之前使用gcc 4.8编译的库.
在我的笔记本电脑上(最新的kubuntu)我有GCC 5.2.当我安装boost时,似乎它使用了新的ABI,但后来我得到了以下链接错误
未定义的符号.....__ cxx11 ....
如何使用旧的ABI和GCC5安装boost?
我的印象是每当你做其中一件时:
virtual void aMethod();void aMethod();virtual void aMethod override;实际上是打破了二进制兼容性,这意味着如果一个项目构建在以前版本的DLL上,那么现在有了新方法可用,它将无法加载它.
根据我使用Visual Studio 2012测试的内容,这些都没有破坏任何东西.Dependency Walker报告没有错误,我的测试应用程序正在调用适当的方法.
DLL:
class EXPORT_LIB MyClass {
public:
void saySomething();
}
Run Code Online (Sandbox Code Playgroud)
可执行文件:
int _tmain(int argc, _TCHAR* argv[])
{
MyClass wTest;
wTest.saySomething();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我发现的唯一未定义的行为是,如果MyClass实现了一个纯虚拟接口,并且从我的可执行文件中,我调用了一个纯虚方法,然后在我的可执行文件使用的方法之前添加了一个新的纯虚方法.在这种情况下,Dependency Walker没有报告任何错误,但在运行时,它实际上调用了错误的方法.
class IMyInterface {
public:
virtual void foo();
}
Run Code Online (Sandbox Code Playgroud)
在可执行文件中
IMyInterface* wTest = new MyClass();
wTest->foo();
Run Code Online (Sandbox Code Playgroud)
然后我更改界面而不重建我的可执行文件
class IMyInterface {
public:
virtual void bar();
virtual void foo();
}
Run Code Online (Sandbox Code Playgroud)
它现在正静静地呼唤bar()而不是foo().
做我所有的三个假设是否安全?
编辑:
这样做
class EXPORT_LIB MyClass …Run Code Online (Sandbox Code Playgroud) 假设我有一个声明函数返回const类型的库:
class Foo { ... };
const Foo makeFoo();
Run Code Online (Sandbox Code Playgroud)
现在我想const从makeFoo()返回类型中删除(请参阅我之前的问题).我可以const从头文件和cpp文件中删除它们,重建库,并将我的代码链接到新库.但是,我还有动态链接到此库的旧代码,我希望它继续使用新版本的库.
那么,第一个问题,是否const从返回类型中删除了ABI?
第二个问题,实际代码是完全不同的:它是一个具有静态成员函数的模板类,稍后将显式实例化:
// fooMaker.h
template<class Foo>
class FooMaker {
public:
static const Foo make();
};
// fooMaker.cpp
template<class Foo>
const Foo FooMaker<Foo>::make() { ... }
template class FooMaker<Foo1>;
template class FooMaker<Foo2>;
Run Code Online (Sandbox Code Playgroud)
它改变了什么吗?
如果这很重要,我在linux下使用g ++.
我正在用C编写一个独立程序,它只依赖于Linux内核.
我研究了相关手册 页,得知X86-64上的Linux系统调用入口点接收通过七个寄存器的系统调用号和六个参数rax,rdi,rsi,rdx,r10,r8,和r9.
这是否意味着 每个系统调用都接受六个参数?
我研究了几个libc实现的源代码,以了解它们如何执行系统调用.有趣的是,musl包含两种不同的系统调用方法:
此汇编源文件定义了一个__syscall函数,该函数将系统调用号和正好六个参数移动到ABI中定义的寄存器.该函数的通用名称暗示它可以与任何系统调用一起使用,尽管它总是将六个参数传递给内核.
此C头文件定义了七个单独的__syscallN函数,并N指定了它们的arity.这表明只传递系统调用所需的确切数量的参数的好处超过了拥有和维护七个几乎相同的函数的成本.
所以我自己尝试了一下:
long
system_call(long number,
long _1, long _2, long _3, long _4, long _5, long _6)
{
long value;
register long r10 __asm__ ("r10") = _4;
register long r8 __asm__ ("r8") = _5;
register long …Run Code Online (Sandbox Code Playgroud) 我正在用 gcc 编译 C++ 程序version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.11)。编译时一切正常。
然后我将这些程序与使用gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3).
然后我收到未定义的参考链接错误:
CMakeFiles/FOSSSim.dir/RigidBodies/RigidBodyGRVelocityProjectionCollisionResolver.cpp.o:(.rodata._ZTV46RigidBodyGRVelocityProjectionCollisionResolver[_ZTV46RigidBodyGRVelocityProjectionCollisionResolver]+0x18): undefined reference to `RigidBodyGRVelocityProjectionCollisionResolver::getName[abi:cxx11]() const'
CMakeFiles/FOSSSim.dir/RigidBodies/RigidBodyGRLCPCollisionResolver.cpp.o:(.rodata._ZTV31RigidBodyGRLCPCollisionResolver[_ZTV31RigidBodyGRLCPCollisionResolver]+0x18): undefined reference to `RigidBodyGRLCPCollisionResolver::getName[abi:cxx11]() const'
CMakeFiles/FOSSSim.dir/RigidBodies/RigidBodyVelocityProjectionCollisionResolver.cpp.o:(.rodata._ZTV44RigidBodyVelocityProjectionCollisionResolver[_ZTV44RigidBodyVelocityProjectionCollisionResolver]+0x18): undefined reference to `RigidBodyVelocityProjectionCollisionResolver::getName[abi:cxx11]() const'
CMakeFiles/FOSSSim.dir/RigidBodies/RigidBodyLCPCollisionResolver.cpp.o:(.rodata._ZTV29RigidBodyLCPCollisionResolver[_ZTV29RigidBodyLCPCollisionResolver]+0x18): undefined reference to `RigidBodyLCPCollisionResolver::getName[abi:cxx11]() const'
CMakeFiles/FOSSSim.dir/RigidBodies/RigidBodyAllPairsCollisionDetector.cpp.o:(.rodata._ZTV34RigidBodyAllPairsCollisionDetector[_ZTV34RigidBodyAllPairsCollisionDetector]+0x18): undefined reference to `RigidBodyAllPairsCollisionDetector::getName[abi:cxx11]() const'
Run Code Online (Sandbox Code Playgroud)
通过一些谷歌搜索,我发现了一些链接,例如linking-problems-due-to-symbols-with-abicxx11处理-D_GLIBCXX_USE_CXX11_ABI=0编译选项。不幸的是,当我使用该选项时,我收到了 Cmake 警告:
CMake Warning:
Manually-specified variables were not used by the project:
_GLIBCXX_USE_CXX11_ABI
Run Code Online (Sandbox Code Playgroud)
解决问题的方法有什么线索吗?知道我宁愿避免更改编译器版本。
谢谢。
我正面临分发编译的 swift 框架的问题。我的框架严重依赖 libxml2 动态库。为了避免Swift 模块兼容性问题,我设置了构建标志 BUILD_LIBRARY_FOR_DISTRIBUTION = YES。
所以我使用 Xcode 11.3 Swift v5.1.3 来构建我的框架。我已将其集成到 Demo.app 项目中。正如预期的那样,Demo.app 在 Xcode 11.3 中运行良好。
但是,我在尝试在 Xcode 11.0 Swift 5.1 中构建 Demo.app 时遇到了另一个错误。我有错误:
#import "libxml/HTMLparser.h"
^
/Applications/Xcode_11.0.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs/AppleTVSimulator13.0.sdk/usr/include/libxml2/libxml/HTMLparser.h:15:10: error: 'libxml/xmlversion.h' file not found
#include <libxml/xmlversion.h>
^
/.../DemoApp/ThirdParty/testXML.framework/Modules/testXML.swiftmodule/x86_64-apple-tvos-simulator.swiftinterface:6:8: error: could not build Objective-C module 'libxml2'
import libxml2
^
/.../DemoApp/AppDelegate.swift:11:8: error: failed to load module 'testXML'
import testXML
Run Code Online (Sandbox Code Playgroud)
我在同一台 Mac 上同时使用两个 Xcode 版本。