如何解决 OS X 上 libobjc.Alibicucore.dylibb 造成的的内存泄露问题

linker - Trouble when linking Objective-C program with my own libobjc.A.dylib - Stack Overflow
to customize your list.
Join the Stack Overflow Community
Stack Overflow is a community of 6.5 million programmers, just like you, helping each other.
J it only takes a minute:
I builded a custom libobjc.A.dylib from the source of apple's open source website and I want to debug it by compiling a simple program with the dylib, but it seems the clang always using the system libobjc.A.dylib.
The compile command is:
xcrun --sdk macosx10.8 clang main.m -std=c99 -framework Foundation -lobjc -I./usr/include -L.
the libobjc.A.dylib is in the current folder. And the otool command tells me which library the program links with:
~ otool -L a.out
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 945.18.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 744.19.0)
file, it's using a flag called -fno-objc-link-runtime, but it seems it's not working with my laptop(mac 10.9.4, xcode 5.1.1)
Tried setting DYLD_LIBRARY_PATH environment var, but it's not working. Here is the folder which I compiled the code , any suggestion or solution?
Actually, I used install_name_tool command to change the library's link:
install_name_tool -change /usr/lib/libobjc.A.dylib @executable_path/libobjc.A.dylib main
Useful links:
Your Answer
Sign up or
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Post as a guest
By posting your answer, you agree to the
Not the answer you're looking for?
Browse other questions tagged
Stack Overflow works best with JavaScript enabledios - libobjc.A.dylib`objc_msgSend: EXC_BAD_ACCESS - Stack Overflow
to customize your list.
Join the Stack Overflow Community
Stack Overflow is a community of 6.5 million programmers, just like you, helping each other.
J it only takes a minute:
I get this error code when I ran the program on my iphone 5s iOS 7.1 or 7.1.1 it works just fine on the iOS simulator.
libobjc.A.dylib`objc_msgSend:
0x objc_msgSend + 112
x13, [x0, 0]
0x1903a01cc:
x9, x13, #0x1fffffff8
x10, x11, [x9, #16] // this line gives an error
w12, w1, w11
x12, x10, x12, lsl #4
Error is : Thread 10:EXC_BAD_ACCESS( code =1,address=0x1a15cbeb8)
This is the code that return the error but only if offline. I use a coredata to save the values.
if([[purchased objectAtIndex:locator]boolValue])
NSAttributedString *theAttributedS
theAttributedString = [[NSAttributedString alloc] initWithString:cellLabel.text
attributes:@{NSStrikethroughStyleAttributeName:
[NSNumber numberWithInteger:NSUnderlineStyleSingle]}];
cellLabel.attributedText = theAttributedS
[cellLabel setTextColor:[UIColor colorWithRed:163/255.0f green:135/255.0f blue:138/255.0f alpha:1.0f]];
[cellLabel1 setTextColor:[UIColor colorWithRed:189/255.0f green:167/255.0f blue:169/255.0f alpha:1.0f]];
imgView.image = [UIImage imageNamed: @"checkbox-checked.png"];
[cellLabel setTextColor:[UIColor colorWithRed:60/255.0f green:0/255.0f blue:0/255.0f alpha:1.0f]];
[cellLabel1 setTextColor:[UIColor colorWithRed:80/255.0f green:37/255.0f blue:37/255.0f alpha:1.0f]];
imgView.image = [UIImage imageNamed: @"checkbox.png"];
I found out what crashes the program. Its this little fella.
cellLabel.attributedText = theAttributedS
Why does it work onnline but when u go offline is beyond me. Can any one explain ?
This is what i get when i enable zombies.
[NSStringDrawingTextStorage textContainerForAttributedString:containerSize:lineFragmentPadding:]: message sent to deallocated instance 0x
159k18193241
Know someone who can answer? Share a link to this
via , , , or .
Your Answer
Sign up or
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Post as a guest
By posting your answer, you agree to the
Browse other questions tagged
Stack Overflow works best with JavaScript enabled1070人阅读
ios点滴(6)
& & & & 最近在开发一个App需要以root权限运行,其中用到一个第三方合作开发的动态库。用theos创建工程,编译,打包,安装都没有问题,但是在手机上点击运行的时候崩溃,崩溃日志如下:
{&bundleID&:&com.yourcompany.packetcapturedemo001&,&app_name&:&PacketCaptureDemo001&,&share_with_app_devs&:false,&name&:&PacketCaptureDemo001&,&app_version&:&&,&is_first_party&:true,&os_version&:&iPhone OS 8.1.2 (12B440)&,&bug_type&:&109&,&slice_uuid&:&d4-32ec-b89e-e5c173a3b876&,&build_version&:&1.0&,&adam_id&:0}
Incident Identifier: 6FC414F6-191C-4A20-ACA5-E918
CrashReporter Key:
dcaf417a1be906ffdddba183cd8c64
Hardware Model:
PacketCaptureDemo001 [1039]
/private/var/db/stash/_.pDSZup/Applications/PacketCaptureDemo001.app/PacketCaptureDemo001
Identifier:
com.yourcompany.packetcapturedemo001
Code Type:
ARM (Native)
Parent Process:
launchd [1]
Date/Time:
16:41:51.594 +0800
Launch Time:
16:41:51.237 +0800
OS Version:
iOS 8.1.2 (12B440)
Report Version:
Exception Type:
EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x00000e7ffdefe
Triggered by Thread:
Dyld Error Message:
Library not loaded: libmt.dylib
Referenced from: /private/var/db/stash/_.pDSZup/Applications/PacketCaptureDemo001.app/PacketCaptureDemo001
Reason: unsafe use of relative rpath libmt.dylib in /private/var/db/stash/_.pDSZup/Applications/PacketCaptureDemo001.app/PacketCaptureDemo001 with restricted binary
Dyld Version: 353.6
Binary Images:
0x1fe67000 - 0x1fe8afff dyld armv7s
&8ffd813a380c333bbd4a25e1dbe05715& /usr/lib/dyld
0x248e0000 - 0x24c0dfff CoreFoundation armv7s
&5b369b45eaa35c3940be& /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
0x24c0e000 - 0x24d38fff CoreGraphics armv7s
&7f42b32bb893c5832f42& /System/Library/Frameworks/CoreGraphics.framework/CoreGraphics
0x - 0x25828fff Foundation armv7s
&b530f5ae7a6b& /System/Library/Frameworks/Foundation.framework/Foundation
0x27e9a000 - 0x2873cfff UIKit armv7s
&94d79df43f8a3b519b7fbf2ca102b4ea& /System/Library/Frameworks/UIKit.framework/UIKit
0x - 0x32390fff libobjc.A.dylib armv7s
&2f24d570ec4104a66ffff& /usr/lib/libobjc.A.dylib& & & & 用otool -L DYLIB_NAME命令对比这个动态库和其他库,如下:
& & & & 出错的库:
libmt.dylib:
libmt.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version )
& & & & 正常的库:
libtest.dylib:
/usr/lib/libtest.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version )
... ...& & & & 可见是库文件查找路径的问题,google查阅一番后,可通过install_name_tool命令修改库的查找路径,具体做法如下:
install_name_tool -id /usr/lib/libmt.dylib libmt.dylib& & & & 再用otool -L libmt.dylib查看文件信息,如下:
libmt.dylib:
/usr/lib/libmt.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version )
... ...& & & & 用此修改过的库文件替换原来的库文件,重新编译打包安装后,就可以直接运行了。
& & & & 附:如果不赋予这个App系统用户的权限,则不需要做上述修改就能正常运行,不知道这是为什么?还得进一步挖掘...
& & & & 参考链接:
& & & & & & & & & & & & &&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:3217次
排名:千里之外ARC 下内存泄露的那些点Archives iOS在网上搜了一下,发现这篇文章是第一篇、也是唯一 一篇总结 ARC 内存泄露的博客,哈哈好兴奋。在 iOS 4.2 时,苹果推出了 ARC 的内存管理机制。这是一种编译期的内存管理方式,在编译时,编译器会判断 Cocoa 对象的使用状况,并适当的加上 retain 和 release,使得对象的内存被合理的管理。所以,ARC 和 MRC 在本质上是一样的,都是通过引用计数的内存管理方式。然而 ARC 并不是万能的,有时为了程序能够正常运行,会隐式的持有或复制对象,如果不加以注意,便会造成内存泄露!今天就列举几个在 ARC 下容易产生内存泄露的点,和各位童鞋一起分享下。block 系列在 ARC 下,当 block 获取到外部变量时,由于编译器无法预测获取到的变量何时会被突然释放,为了保证程序能够正确运行,让 block 持有获取到的变量,向系统显明:我要用它,你们千万别把它回收了!然而,也正因 block 持有了变量,容易导致变量和 block 的循环引用,造成内存泄露! /** * 本例取自《Effective Objective-C 2.0》 * * NetworkFetecher 为自定义的网络获取器的类 */ //EOCNetworkFetcher.h#import &Foundation/Foundation.h&typedef void (^EOCNetworkFetcherCompletionHandler)(NSData *data);@interface EOCNetworkFetcher : NSObject@property (nonatomic, strong, readonly) NSURL *url;- (id)initWithURL:(NSURL *)url;- (void)startWithCompletionHandler:(EOCNetworkFetcherCompletionHandler)completion;@end;//EOCNetworkFetcher.m#import "EOCNetworkFetcher.h"@interface EOCNetworkFetcher ()@property (nonatomic, strong, readwrite) NSURL *url;@property (nonatomic, copy) (EOCNetworkFetcherCompletionHandler)completionHandler;@property (nonatomic, strong) NetworkFetecher *networkFetecher;@end;@implementation EOCNetworkFetcher- (id)initWithURL:(NSURL *)url{
if (self = [super init]) {
_url = url;
return self;}- (void)startWithCompletionHandler:(EOCNetworkFetcherCompletionHandler)completion{
self.completionHandler = completion;
*/}- (void)p_requestCompleted{
if (_completionHandler) {
_completionHandler(_downloaderData);
}}/** * 某个类可能会创建网络获取器,并用它从 URL 中下载数据 */@implementation EOCClass {
EOCNetworkFetcher *_networkFetcher;
NSData *_fetcherData;}- (void)downloadData{
NSURL *url = [NSURL alloc] initWithString:@"/* some url string */";
_networkFetcher = [[EOCNetworkFetch alloc] initWithURL:url];
[_networkFetcher startWithCompletionHandler:^(NSData *data) {
NSLog(@"request url %@ finished.", _networkFetcher);
_fetcherData = data;
}]}@end;这个例子的问题就在于在使用 block 的过程中形成了循环引用:self 持有 networkFetecher;networkFetecher 持有 block;block 持有 self。三者形成循环引用,内存泄露。// 例2:block 内存泄露- (void)downloadData{
NSURL *url = [[NSURL alloc] initWithString:@"/* some url string */"];
NetworkFetecher *networkFetecher = [[NetworkFetecher alloc] initWithURL:url];
[networkFetecher startWithCompletionHandler:^(NSData *data){
NSLog(@"request url: %@", networkFetcher.url);
}];}这个例子比上个例子更为隐蔽,networkFetecher 持有 block,block 持有 networkFetecher,形成内存孤岛,无法释放。说到底原来就是循环引用搞的鬼。循环引用的对象是首尾相连,所以只要消除其中一条强引用,其他的对象都会自动释放。对于 block 中的循环引用通常有两种解决方法
将对象置为 nil ,消除引用,打破循环引用;
将强引用转换成弱引用,打破循环引用;
// 将对象置为 nil ,消除引用,打破循环引用/*这种做法有个很明显的缺点,即开发者必须保证 _networkFetecher = 运行过。若不如此,就无法打破循环引用。但这种做法的使用场景也很明显,由于 block 的内存必须等待持有它的对象被置为 nil 后才会释放。所以如果开发者希望自己控制 block 对象的生命周期时,就可以使用这种方法。*/// 代码中任意地方_networkFetecher = nil;- (void)someMethod{
NSURL *url = [[NSURL alloc] initWithString:@"g.cn"];
_networkFetecher = [[NetworkFetecher alloc] initWithURL:url];
[_networkFetecher startWithCompletionHandler:^(NSData *data){
self.data = data;
}];}// 将强引用转换成弱引用,打破循环引用__weak __typeof(self) weakSelf = self;NSURL *url = [[NSURL alloc] initWithString:@"g.cn"];_networkFetecher = [[NetworkFetecher alloc] initWithURL:url];[_networkFetecher startWithCompletionHandler:^(NSData *data){
//如果想防止 weakSelf 被释放,可以再次强引用
__typeof(&*weakSelf) strongSelf = weakSelf;
if (strongSelf)
//do something with strongSelf
}}];代码 __typeof(&*weakSelf) strongSelf 括号内为什么要加 &* 呢?主要是为了兼容早期的 LLVM,更详细的原因见:block 的内存泄露问题包括自定义的 block,系统框架的 block 如 GCD 等,都需要注意循环引用的问题。有个值得一提的细节是,在种类众多的 block 当中,方法名带有 usingBlock 的 Cocoa Framework 方法或 GCD 的 API ,如- enumerateObjectsUsingBlock:
- sortUsingComparator:
这一类 API 同样会有循环引用的隐患,但原因并非编译器做了保留,而是 API 本身会对传入的 block 做一个复制的操作。performSelector 系列performSelector 顾名思义即在运行时执行一个 selector,最简单的方法如下- (id)performSelector:(SEL)
这种调用 selector 的方法和直接调用 selector 基本等效,执行效果相同[object methodName];
[object performSelector:@selector(methodName)];
但 performSelector 相比直接调用更加灵活SEL selector;if (/* some condition */) {
selector = @selector(newObject);} else if (/* some other condition */) {
selector = @selector(copy);} else {
selector = @selector(someProperty);}id ret = [object performSelector:selector];这段代码就相当于在动态之上再动态绑定。在 ARC 下编译这段代码,编译器会发出警告warning: performSelector may cause a leak because its selector is unknow [-Warc-performSelector-leak]
正是由于动态,编译器不知道即将调用的 selector 是什么,不了解方法签名和返回值,甚至是否有返回值都不懂,所以编译器无法用 ARC 的内存管理规则来判断返回值是否应该释放。因此,ARC 采用了比较谨慎的做法,不添加释放操作,即在方法返回对象时就可能将其持有,从而可能导致内存泄露。以本段代码为例,前两种情况(newObject, copy)都需要再次释放,而第三种情况不需要。这种泄露隐藏得如此之深,以至于使用 static analyzer 都很难检测到。如果把代码的最后一行改成[object performSelector:selector];
不创建一个返回值变量测试分析,简直难以想象这里居然会出现内存问题。所以如果你使用的 selector 有返回值,一定要处理掉。performSelector 的另一个可能造成内存泄露的地方在编译器对方法中传入的对象进行保留。据说有位苦命的兄弟曾被此问题搞得欲仙欲死,详情围观 addObserver 系列addObserver 即 Objective-C 中的观察者,此系列常见于 NSNotification、KVO 注册通知。注册通知时,为了防止 observer 被突然释放,造成程序异常,需要持有 observer,这是造成内存泄露的一个隐患之一。所以为什么需要在代码的 dealloc 方法中移除通知,原因就在于此。NSNotificationcenter 需要 removeObserver 的原因是如果不移除的话,被观察者那么还会继续发送消息。如果此时观察者已经释放,消息会转发给其他对象,有可能造成严重的问题。在使用 NSTimer addtarget 时,为了防止 target 被释放而导致的程序异常,timer 会持有 target,所以这也是一处内存泄露的隐患。// NSTimer 内存泄露/** * self 持有 timer,timer 在初始化时持有 self,造成循环引用。 * 解决的方法就是使用 invalidate 方法销掉 timer。 */// interface@interface SomeViewController : UIViewController@property (nonatomic, strong) NSTimer *timer;@end//implementation@implementation SomeViewController- (void)someMethod{
timer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:@selector(handleTimer:)
userInfo:nil
repeats:YES];
}@endtry...catch做了一年多的 iOS 开发,一开始看到 try...catch 的第一反应是:这什么鬼?怎么从来没听过?确实,try...catch 实在太低调了,当然这也是有原因的,后面会说。Apple 提供了 (NSError)和 (NSException)两种机制,而 try...catch 就是使用 exception 捕获异常。NSError 应用在在绝大部分的场景下,并且这也是 Apple 所推荐。那什么时候用 NSException 呢?在极其严重的直接导致程序崩溃情况下才使用,并且无需考虑恢复问题。水平和经验所限,我也没有使用过 exception,但可以举个系统使用 exception 的例子NSArray *array = @[@"a", @"b", @"c"];[array objectAtIndex:3];这小段代码一执行,马上崩溃,有提示信息2015-03-08 21:38:02.346 HelloWorldDemo[87324:1024731] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 3 beyond bounds [0 .. 2]'*** First throw call stack:(
* 这中间省略了的东西是栈回溯信息,如
CoreFoundation
0x045a0946 __exceptionPreprocess + 182
libobjc.A.dylib
0x041fba97 objc_exception_throw + 44
CoreFoundation
0x04483bd2 -[__NSArrayI objectAtIndex:] + 210
*/)libc++abi.dylib: terminating with uncaught exception of type NSException很熟悉对吧,原来我们平时看到的各种崩溃提示信息,用的就是 exception。Objective-C 的 try...catch 的语法格式和 C++/Java 类似,如下@try {
// 可能抛出异常的代码}@catch (NSException *exception) {
// 处理异常}@finally {
// finally 代码块是可选的
// 但如果写了 finally block,不管有没有异常,block 内的代码都会被执行}以前面 NSArray 的越界访问为例,即可写成如下代码NSArray *array = @[@"a", @"b", @"c"];@try {
// 可能抛出异常的代码
[array objectAtIndex:3];}@catch (NSException *exception) {
// 处理异常
NSLog(@"throw an exception: %@", exception.reason);}@finally {
NSLog(@"finally execution");}使用了 try...catch 后,代码就不会崩溃,执行后打印如下信息2015-03-08 22:36:34.729 HelloWorldDemo[87590:1066344] throw an exception: *** -[__NSArrayI objectAtIndex:]: index 3 beyond bounds [0 .. 2]2015-03-08 22:36:34.729 HelloWorldDemo[87590:1066344] finally execution那 try...catch 哪里会有内存泄露的隐患呢?我们先看 MRC 下的情况// MRC 下的 try...catch// 注意:在 @try @catch @finally 块内定义的变量都是局部变量@try {
EOCSomeClass *object = [[EOCSomeClass alloc] init];
[object doSomethingMayThrowException];
[object release];}@catch (NSException *exception) {
NSLog(@"throw an exception: %@", exception.reason);}此处看似正常,但如果 doSomethingMayThrowException 方法抛出了异常,那么 object 对象就无法释放。如果 object 对象持有了重要且稀缺的资源,就可能会造成严重后果。ARC 的情况会不会好点儿呢?其实更糟糕。我们以为 ARC 下,编译器会替我们做内存释放,其实不会,因为这样需要加入大量的样板代码来跟踪清理对象,从而在抛出异常时将其释放。即使这段代码即使不抛出异常,也会影响运行期的性能,而且增加进来的额外代码也会增加应用程序的体积,这些副作用都是很明显的。但另一方面,如果程序都崩溃了,回不回收内存又有什么意义呢?所以可以总结下 try...catch 绝迹的原因:
try...catch 设计的目的是用来捕获程序崩溃的情况。
如果为了捕获异常,而在代码中添加 try...catch 和安全处理异常的代码,就会影响性能,增加应用体积。
总结众观全文,ARC 下的内存泄露问题仅仅是由于编译器采用了较为谨慎的策略,为了保证程序能够正常运行,而隐式的复制或持有对象。只要代码多加注意,即可避免很多问题。本文总结可能不够完整,如还有遗漏的地方,请到新浪微博
告诉我,我会尽力补全。
添加新批注
在作者公开此批注前,只有你和作者可见。
查看更早的 5 条回复iOS(401)
Shared by eric&
mac osx的dyld是挺烦的
所谓dylib,就是bsd风格的动态库。基本可以认为等价于windows的dll和linux的so。mac基于bsd,所以也使用的是dylib。
如果你需要引用一个第三方的dylib,在xcode下编译出cocoa程序,在本机上运行是不会出问题的。但是发布出来,给其他用户用,就可能出问题。因为用户不一定有这个库。
这个问题给我造成了相当的困扰,我到现在也没找到正规的方法。但是我确实解决了这个问题,虽然方法不一定正宗。不管怎么说,写下来,如果暂时没有更好的办法,那么先这样做。如果谁有更好的办法,也请一定不吝留言或邮件给我。
我的办法是这样的:
1 otool -L yourapp.app/Contents/MacOS/yourapp
这一步的意思是对你编译出的app使用otool命令,以便获得依赖哪些dylib的信息。注意这个路径。cocoa的app在命令行下表现为目录。所有相关的东西都在里面。
结果如下所示:
yourapp.app/Contents/MacOS/yourapp:
/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 12.0.0)
/usr/local/lib/lib01.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/local/lib/lib02.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/local/lib/lib03.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 476.0.0)
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 949.0.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 677.12.0)
注意我标红的地方。假如lib01,lib02,lib03是本程序引用的第三方库,那么在这个程序里面,他们的引用地址是位于/usr/local/lib上的。这是开发机上的安装情况。而使用这个程序的客户机未必安装这些东西,所以程序就要出错。
显然,我们需要做2件事。a 把这些库附带在app上 b 把他们的引用地址修改到正确的位置。
2 mkdir yourapp.app/Contents/dylib
在编译出来的app中,创建dylib目录
然后把所有需要的库复制过去
cp /usr/local/lib/lib01.dylib yourapp.app/Contents/dylib/
cp /usr/local/lib/lib02.dylib yourapp.app/Contents/dylib/
cp /usr/local/lib/lib03.dylib yourapp.app/Contents/dylib/
3 install_name_tool -change /usr/local/lib/lib01.dylib @loader_path/../dylib/lib01.dylib &yourapp.app/Contents/MacOS/yourapp&
install_name_tool 是苹果提供的用来修改dylib安装名称的命令。这个命令执行之后,再用otool -L 就可以看到变化了
yourapp.app/Contents/MacOS/yourapp:
/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 12.0.0)
@loader_path/../dylib/lib01.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/local/lib/lib02.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/local/lib/lib03.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 476.0.0)
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 949.0.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 677.12.0)
注意标红的位置。已经变化了。@loader_path 指的是应用程序运行的位置,也就是yourapp.app/Contents/MacOS/yourapp,所以要用一个..,以便定位到第2步创建的dylib目录。
重复这个命令,修改lib02,lib03
4 otool -L yourapp.app/Contents/dylib/*.dylib
继续用otool 来检查dylib下面使用的第三方库是否还有其他依赖,install_name是否正确,重复1,2,3的步骤,把所需要的dylib复制过来,修改install_name。
如果都改对了,那么这个app就附带上了dylib,可以在其他机器上正确运行了,不用非要寻找/usr/local/lib下面的库了。
刚才我们修改的结果是一个build的结果。当然,每次build都这么折腾一下很麻烦。所以继续这样做:
1 前面的步骤得到了一个完整的dylib目录。把这个dylib复制一份备用。比如放在你的xcode项目下面。
2 编写一个脚本:
mkdir &$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/dylib&
cp -f /your/path/to/xcode_project_name/dylib/*.dylib &$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/dylib/&
install_name_tool -change /usr/local/lib/lib01.dylib @loader_path/../dylib/lib01.dylib &$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME&
(用这个格式重复前面对app使用过的dylib)
3 在xcode中,展开targets节点,右键点工程名称,在菜单中选Add-&New Build Phasa-&New Run Script Build Phasa,在打开的对话框里面,把刚才的脚本贴进去。如图所示。
这个脚本会在build之后自动运行。不过我这里有个奇怪的问题,如果Shell里面写了/bin/sh,会报告找不到这个文件(实际上存在),而让shell为空,反而可以正确的运行shell命令。
经过这些处理,每次编译出来的app就可以拿到其他机器上运行了。可真够麻烦的...
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1509716次
积分:14983
积分:14983
排名:第574名
原创:54篇
转载:880篇
评论:79条
(1)(1)(15)(21)(4)(6)(42)(4)(1)(5)(2)(11)(18)(21)(43)(3)(4)(11)(5)(3)(2)(7)(2)(4)(39)(60)(24)(86)(118)(92)(2)(2)(2)(1)(5)(18)(3)(17)(20)(97)(59)(35)(20)(1)}

我要回帖

更多关于 libiconv.dylib 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信