假设我们class X在程序集的版本1中A.dll:
class X {
SomeType Property { set; get; }
}
Run Code Online (Sandbox Code Playgroud)
然后在程序集的第2版中A.dll:
class X {
SomeType Property { set; get; }
SomeType OtherProperty { set; get; }
}
Run Code Online (Sandbox Code Playgroud)
现在假设我们有第二个B.dll加载A.dll和使用X的程序集.是否会添加属性会OtherProperty破坏ABI?将B.dll无法使用A.dll/ X?如果没有,声明的顺序会有什么不同吗?如果属性是虚拟的,它有什么不同吗?
我想我真的在问:ABI的一般规则是什么?我知道在发布之后更改接口是一件坏事,但我真的希望能够在某些情况下添加属性,而无需添加子类.
Objective-C 2.0 ABI的文档是否存在于Internet上的某个位置?该发行说明的objc4-493.9说:
即将出版的文档将仅描述使用编译器和开发人员工具的ABI.
它已经发布了吗?最接近的此类引用是Apple的Objective-C运行时引用,但这仅描述面向公众的API而不是实现细节.事实上,它甚至提到了ABI:
此外,新的Objective-C ABI(此处未描述)[...]
不幸的是,新的ABI在上述文本中没有超链接.:-)是我唯一的选择,以了解objc4运行时和Clang的CGObjCNonFragileABIMac代码生成项目的源代码?
我需要部署到Red Hat 4.1.2框(具有gcc 4.1.2).我在Ubuntu 11.10上使用GCC 4.6.1进行开发.不幸的是,我的构建过程创建的一些二进制文件在RedHat机器上不可用.原因似乎是ABI更改,根据另一个Stackoverflow问题导致STT_GNU_IFUNC符号的引入.有没有办法阻止导出任何这样的符号,以便我的二进制文件可以使用旧的ABI?我使用nm在我的二进制文件中查找"i"类型的任何符号,但没有找到.
我问这个,因为我的一些其他的二进制文件,以及一些第三方库我建(TBB,升压),不使用新的ABI等运行RedHat的机器上的罚款.
希望很清楚.提前致谢.
我最近花了相当多的时间来追踪一个问题,原因是编译了一个库-D_GLIBCXX_DEBUG(告诉libstdc ++使用带有额外检查的标准库的调试版本),但没有编译客户端程序.这导致了ABI兼容性问题.
有什么方法可以通过GCC自动检测这样的问题吗?Visual Studio提供了我认为可以用于此目的的detect_mismatch编译指示,但我不知道任何GCC等价物.GCC通过嵌入符号名称(例如GLIBCXX_3.4.9)做了一些事情,我可以想象如果相应的符号(例如mylib_debug_stl)不存在则会因为未定义的符号而导致链接错误的方案,但是我能想到的唯一方法是使用那个符号真是太烂了.
或者,其他人如何避免这个问题?将库的已检查版本构建为不同的名称或类似的名称?
使用WIN32上的Visual C++,具有4个或更多SSE参数的函数存在长期存在的问题,例如
__m128i foo4(__m128i m0, __m128i m1, __m128i m2, __m128i m3) {}
Run Code Online (Sandbox Code Playgroud)
生成错误:
align.c(8) : error C2719: 'm3': formal parameter with __declspec(align('16')) won't be aligned
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,即使函数是,Visual C++仍然会不必要地强加ABI限制__inline.
我想知道这是否仍然是64位Windows上的问题?ABI限制是否仍适用于x64?
(我无法访问64位Windows系统,否则我会亲自尝试,并且广泛的Google搜索没有发现任何确定的内容.)
在函数中使用struct参数时,clang将更改函数签名.签名将是一个相同大小的强制int,而不是使用结构类型.在我的编译器项目中,我使用llvm结构类型作为方法签名(这似乎更合乎逻辑).
这不会是一个问题,除了LLVM在使用struct或coerced类型时产生的汇编是不同的而不是调用兼容的事实.这导致我的编译器不与具有结构的C函数ABI兼容.
为什么clang这样做?这是C ABI中指定的内容吗?
这是一个简单的示例C源文件:
struct TwoInt { int a, b; };
struct EightChar { char a, b, c, d, e, f, g, h; };
void doTwoInt(struct TwoInt a) {}
void doEightChar(struct EightChar a) {}
int main()
{
struct TwoInt ti;
struct EightChar fc;
doTwoInt(ti);
doEightChar(fc);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
从Clang得到的LLVM-IR
%struct.TwoInt = type { i32, i32 }
%struct.EightChar = type { i8, i8, i8, i8, i8, i8, i8, i8 }
define void @doTwoInt(i64 %a.coerce) nounwind uwtable {
%a …Run Code Online (Sandbox Code Playgroud) 我不明白为什么ABI是开发用户空间应用程序的重要环境.是否将操作系统的系统调用集视为ABI?但是,如果是这样,那么关于标准库中封装的系统调用的所有复杂性是不是都很复杂?
那么ABI兼容性仅与在不同平台上运行静态链接应用程序相关,因为系统调用将嵌入到二进制文件中?
我想明白为什么内联函数的libc ++可见性宏使用__forceinline或__attribute__((__always_inline__))作为与内联函数关联的属性的一部分.
有关背景,请参阅
如果这些内联函数将被标记为__visibility__("hidden")无论如何,为什么还需要强制编译器内联它们?
我已经考虑了一下,我有一些假设,但似乎没有一个对我完全满意:
hidden属性不足够吗?同样,在构建库时是否只需要强制内联函数?消费者不应该在意.visibility("hidden")吗?我问这个是因为我正在构建一个C++库,我希望有一天能够标准化ABI,我正在使用libc ++作为指导.到目前为止,它运作良好,但这个问题引起了一些人头疼.
特别是,我们有报道称用户抱怨MSVC拒绝遵守该__forceinline属性,从而导致警告.我们提出的解决方案是__forceinline在构建库时将模拟扩展到INLINE_VISIBILITY仅包括(或GCC等效),假设上面的第一个解释.
但是,由于我们并不完全相信我们理解强制内联函数背后的原因,__forceinline或者__attribute__((__always_inline__))首先,我们对采用这种解决方案有点犹豫不决.
任何人都可以提供一个明确的答案,为什么libc ++需要强制内联其内联函数,即使它们已被装饰为具有隐藏的可见性?
我正在Linux上构建一个共享库,它作为某些软件的"插件"(具体来说,它扩展了Mathematica).
我发现如果我构建在Ubuntu 16.04上,生成的库在RHEL 7.6上不起作用.但是,如果我在RHEL 7.6上构建,那么该库可以在RHEL和Ubuntu上运行.
通过"不工作",我指的是数学拒绝加载它,但它只是给出了一个通用的,无用的"加载失败"错误消息.
我已经消除了许多可能破坏兼容性的因素,我找不到了.这个问题是关于其他可能影响兼容性的问题,而不是我在下面列出
该库是用C和C++混合编写的,但它导出了一个C接口.它是用-static-libstdc++和建造的-static-libgcc.如果我ldd在.so文件上使用它,它列出的唯一依赖项是:
linux-vdso.so.1 => (0x00007ffc757b9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa286e62000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa287854000)
Run Code Online (Sandbox Code Playgroud)
不兼容的一个潜在来源是glibc版本.我查看了库中的符号,nm -gC我在Ubuntu上构建的最高GLIBC版本参考是2.14.RHEL 7.6有glibc 2.17,比2.14更新.因此,我不认为不相容是由于glibc.
还有什么可以导致在Ubuntu 16.04上编译的共享对象不能在RHEL 7.6上加载?
更新:我设法哄Mathematica给出一个更具描述性的错误(这是一个记录不完整的功能),所以我有一个具体的错误信息.在@ Ctx提出的建议中也可以看到同样的情况LD_DEBUG=all.
错误是:
IGraphM.so: undefined symbol: _ZTVNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEEE
Run Code Online (Sandbox Code Playgroud)
(IGraphM.so是我的图书馆.)
除非我弄错了,否则这个函数似乎是libstdc ++的一部分.如果我指定-static-libstdc++并验证了ldd没有列出libstdc ++ ,为什么会出现此错误?
更新2:
根据SergeyA和本QA的建议,我在定义后编译_GLIBCXX_USE_CXX11_ABI=0. 这确实解决了不兼容问题.
但我仍然不明白为什么.错误消息抱怨缺少符号.这个符号通常从哪里加载?我的印象是,如果我使用-static-libstdc++,那么它应该包含在我的库中.这似乎是错误的.
虽然我似乎有一个实用的解决方案来解决这个特定情况的不兼容性,但我会感谢一些解释,所以将来我可以自己解决类似的问题.