我在Linux上有一个可执行文件加载libfoo.so.1(即a SONAME)作为其依赖项之一(通过另一个共享库).它还链接到另一个系统库,而该系统库又链接到系统版本libfoo.so.2.其结果是,既 libfoo.so.1和libfoo.so.2执行期间被加载,和这应该从库版本1调用函数代码结束调用从一个较新的系统库(二进制不相容)功能与第2版,因为一些符号保持不变.结果通常是堆栈粉碎和随后的段错误.
现在,链接旧版本的库是一个封闭源的第三方库,我无法控制libfoo它编译的版本.假设,剩下的唯一选择是重建当前链接的一堆系统库以libfoo.so.2进行链接libfoo.so.1.
有没有办法避免使用链接到旧版本的本地副本替换系统库libfoo?我可以加载两个库并让代码调用正确的符号版本吗?所以我需要一些特殊的符号级版本控制?
在Objective-C中,如果我想使用仅出现在新版iOS中的特定类,我会这样做:
if( [UIBlurEffect class] ) {
// do something with UIBlurEffect
}
else {
// gracefully fallback to old behavior
}
Run Code Online (Sandbox Code Playgroud)
但是,等效的Swift:
if UIBlurEffect.self != nil {
let blur: UIBlurEffect = UIBlurEffect(...)
// ...
else {
// ...
}
// also occurs with NSClassFromString("UIBlurEffect")
Run Code Online (Sandbox Code Playgroud)
没有相同的功能.
如果在NSNewFeature可用的环境中运行,一切都很好.但是如果未定义类,则在启动应用程序时会出现链接错误:
dyld: Symbol not found: _OBJC_CLASS_$_UIBlurEffect
Run Code Online (Sandbox Code Playgroud)
那么如何在Swift中进行弱链接?
编辑添加UIBlurEffect为特定示例.
我有一个程序(特别是我的SO DevDays倒计时应用挑战的入口),它依赖于几个动态库,即libSDL,libSDL_ttf等.我/opt/local/lib通过MacPorts 安装了这些库,许多人不会安装这些库(有些人可能已经安装了这些库,但是没有安装它们).
如何分发我的程序,以便没有安装这些库的人可以开箱即用?显然我将不得不分发各种.dylib文件,但这样做是不够的.动态加载程序仍然会查找安装在我安装的位置的库.有没有办法告诉动态加载器查看可执行文件的当前目录,比如Windows对DLL的作用?人们不应该修改任何环境变量(例如DYLD_LIBRARY_PATH),因为我再次希望这可以开箱即用.
从共享库/ dll调用函数的最简单,最安全的方法是什么?我最感兴趣的是在linux上这样做,但如果有一个独立于平台的方式会更好.
有人可以提供示例代码来说明如何进行以下工作,用户将自己的版本编译foo到共享库中吗?
// function prototype, implementation loaded at runtime:
std::string foo(const std::string);
int main(int argc, char** argv) {
LoadLibrary(argv[1]); // loads library implementing foo
std::cout << "Result: " << foo("test");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
顺便说一下,我知道如何编译共享的lib(foo.so),我只需要知道在运行时加载它的简单方法.
我有一个用C++编写的服务器应用程序.启动后,它在x86 Linux上使用大约480 KB的内存(Ubuntu 8.04,GCC 4.2.4).我认为480 KB是一个过多的内存:服务器甚至没有做任何事情,没有客户端连接到服务器.(另请参阅下面的评论,其中我解释了为什么我认为480 KB是大量内存.)服务器在初始化期间唯一做的事情就是产生一个或两个线程,设置几个套接字,以及其他简单的东西.非常记忆密集.
请注意,我在谈论实际内存使用情况,而不是VM大小.我通过在空闲笔记本电脑上启动我的服务器的100个实例来测量它,并在启动服务器实例之前和之后用"免费"测量系统内存使用情况.我已经考虑了文件系统缓存和类似的东西.
经过一些测试后,看起来C++运行时中的某些东西会导致我的服务器使用这么多内存,即使服务器本身没有做任何事情.例如,如果我插入
getchar(); return 0;
Run Code Online (Sandbox Code Playgroud)
之后
int main(int argc, char *argv[]) {
Run Code Online (Sandbox Code Playgroud)
然后每个实例的内存使用量仍为410 KB!
我的应用程序仅依赖于Curl和Boost.我有很多C编程经验,我知道C库在使用之前不会增加内存消耗.
我发现的其他事情:
我的结论如下:
我记得几年前关于C++动态链接器问题的一些KDE讨论.之后的Linux C++动态链接器导致KDE C++应用程序启动时间慢,内存消耗大.据我所知,这些问题已在C++运行时修复.但类似的东西可能是我所看到的过度记忆消耗的原因吗?
来自gcc /动态链接专家的答案非常感谢.
对于那些好奇的人,有问题的服务器是Phusion Passenger的日志记录代理:https://github.com/FooBarWidget/passenger/blob/master/ext/common/LoggingAgent/Main.cpp
我遇到了一段使用#pragma comment(lib,"libraryname")的代码.
为什么这种用法与仅从属性菜单链接库相反?在什么情况下需要这种用法?我在使用C++ Visual Studio 2010的 Windows中.
很高兴看到一个需要这种用法的例子.
我正在尝试在MacOSX 10.6上构建一个Python扩展,并将其链接到几个框架(仅限i386).我使用distutils和Extension对象创建了一个setup.py文件.
我命令链接我的框架,我的LDFLAGS env var应该如下:
LDFLAGS = -lc -arch i386 -framework fwk1 -framework fwk2
Run Code Online (Sandbox Code Playgroud)
由于我在Extension模块文档中没有找到任何'framework'关键字,所以我使用了extra_link_args关键字.
Extension('test',
define_macros = [('MAJOR_VERSION', '1'), ,('MINOR_VERSION', '0')],
include_dirs = ['/usr/local/include', 'include/', 'include/vitale'],
extra_link_args = ['-arch i386',
'-framework fwk1',
'-framework fwk2'],
sources = "testmodule.cpp",
language = 'c++' )
Run Code Online (Sandbox Code Playgroud)
一切都在编译和链接很好.如果我从extra_link_args中删除-framework行,我的链接器将按预期失败.这是python setup.py构建产生的最后两行:
/usr/bin/g++-4.2 -arch x86_64 -arch i386 -isysroot /
-L/opt/local/lib -arch x86_64 -arch i386 -bundle
-undefined dynamic_lookup build/temp.macosx-10.6-intel-2.6/testmodule.o
-o build/lib.macosx-10.6-intel-2.6/test.so
-arch i386 -framework fwk1 -framework fwk2
Run Code Online (Sandbox Code Playgroud)
不幸的是,我刚刚制作的.so无法找到这个框架提供的几个符号.我试图用otool检查链接的框架.它们都没有出现.
$ otool -L test.so
test.so:
/usr/lib/libstdc++.6.dylib (compatibility version …Run Code Online (Sandbox Code Playgroud) 为了符合Qt的LGPL许可证,使用Qt库的应用程序必须使源代码可用或动态链接到Qt(如果我用这几个字正确地得到了它).
所以我想创建一个完全正确的闭源应用程序.另外,我想在Linux(目前是Xubuntu 12.04)上使用支持C++ 11的g ++/MinGW来开发Windows二进制文件.我按照这个有用的指南来完成后者.但正如指南还指出的那样,创建了静态链接的可执行文件.
由于我使用MXE自动下载和构建Qt库(版本5.0),因此我没有太多机会影响该过程.所以我的问题是,如何创建Qt库和相应应用程序的动态链接版本?
考虑 Linux 系统上的以下两个文件:
使用消息.cpp
#include <iostream>
extern const char* message;
void print_message();
int main() {
std::cout << message << '\n';
print_message();
}
Run Code Online (Sandbox Code Playgroud)
libmessage.cpp
#include <iostream>
const char* message = "Meow!"; // 1. absolute address of string literal
// needs runtime relocation in a .so
void print_message() {
std::cout << message << '\n';
}
Run Code Online (Sandbox Code Playgroud)
我们可以将use_message.cpp编译为目标文件,将libmessage.cpp编译为共享库,并将它们链接在一起,如下所示:
$ g++ use_message.cpp -c -pie -o use_message.o
$ g++ libmessage.cpp -fPIC -shared -o libmessage.so
$ g++ use_message.o libmessage.so -o use_message
Run Code Online (Sandbox Code Playgroud)
的定义message …
我有两个可执行文件,它们都是交叉编译的,可以在Android中运行.我已将两者放在同一目录中的设备上.我已将它们所依赖的所有共享库放在同一目录中,包括ld-linux.so.3.我使用以下命令运行可执行文件:
ld-linux.so.3 --library-path/path/to/libraries executable_name
当作为任何用户运行时,它们都适用于旧版本的Android.如果以root身份运行,两者都可以在最新版本的Android上运行.当以任何用户身份运行时,只有一个可以在最新版本的android上运行.相反,它给出:
无法从共享对象映射段:不允许执行executable_name操作
如何找出不能运行的可执行文件的不同之处?
我在网上看了很多,大多数人都会收到这个错误:
A)没有它们所依赖的库之一或可执行文件本身的执行权限.
要么
B)尝试从作为NOEXEC挂载的目录运行.
这两种情况似乎并非如此.它可以找到所有库,我可以自己加载任何库,看看它依赖于解决的其他东西.此外,我可以从感兴趣的目录运行基本脚本.
较新版本的Android,Jelly Bean,是一个不同的Linux内核版本,我想知道这是否相关.
什么给?我该如何调试?
dynamic-linking ×10
c++ ×5
elf ×2
linker ×2
linux ×2
macos ×2
abi ×1
android ×1
dll ×1
dyld ×1
executable ×1
gcc ×1
ios ×1
low-level ×1
mxe ×1
objective-c ×1
python ×1
qt ×1
qt5 ×1
relocation ×1
swift ×1
versioning ×1