ios 使用 ARC 查找保留对象的位置
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12262403/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Find where object is retained with ARC
提问by hpique
I have an object that is being retained more than necessary (most likely due to a property that is strong
instead of weak
). Big codebase, so it's hard to find where.
我有一个被保留的对象超过了必要(很可能是由于一个属性strong
而不是weak
)。大代码库,所以很难找到在哪里。
How can I find all the lines in which this object is being retained when using ARC?
使用ARC时如何找到保留该对象的所有行?
If I weren't using ARC I guess I could simply override retain
and check from where it's called. Can I do something similar with ARC?
如果我不使用 ARC,我想我可以简单地覆盖retain
并检查它的调用位置。我可以用 ARC 做类似的事情吗?
回答by bbum
To track growth of an application, Heapshot Analysishas proven very effective. It will capture both true leaks and accretion of memory where the allocations are not accounted for by leaks.
为了跟踪应用程序的增长,Heapshot Analysis已被证明非常有效。它将捕获真正的泄漏和内存增加,其中分配没有被泄漏考虑在内。
You can see all of the retain/release events, and their backtrace, using the Allocations instrument. Hit the little (i) button on the Allocations instrument and turn on "Record reference counts". Turning on "Only track active allocations" reduces the amount of data collected by Instruments, making it snappier (and dead allocations aren't really useful in this context, but can be in others).
您可以使用 Allocations 工具查看所有保留/释放事件及其回溯。点击分配工具上的小 (i) 按钮并打开“记录参考计数”。打开“仅跟踪活动分配”会减少 Instruments 收集的数据量,使其更快速(并且死分配在这种情况下并不是真正有用,但在其他情况下可能有用)。
With that, you can dive into any allocation (by clicking on the right-arrow in the address field), see all the retain/release events and see exactly where they occurred.
有了它,您可以深入了解任何分配(通过单击地址字段中的右箭头),查看所有保留/释放事件并准确查看它们发生的位置。
回答by hpique
I managed to find the offending retain
by doing the following:
我设法retain
通过执行以下操作找到了冒犯之处:
- Temporarily add
-fno-objc-arc
to the object class Compiler Flags to disable ARC for that class. - Temporarily override
retain
(just callsuper
) and put a breakpoint on it. - Debug and check the call stack each time
retain
is called.
- 临时添加
-fno-objc-arc
到对象类 Compiler Flags 以禁用该类的 ARC。 - 临时覆盖
retain
(只需调用super
)并在其上放置一个断点。 - 每次调用时调试并检查调用堆栈
retain
。
回答by Sulthan
Last week I was helping some friends debug leaks in their ARC project. Some tips:
上周我正在帮助一些朋友调试他们 ARC 项目中的漏洞。一些技巧:
1/ Build for Profiling and start Instruments with Leak Detection. Then explore the currently allocated objects, find the object you want (you can sort them by name) and look into its retain/release history. Note that retain count is not very helpful with ARC. You have to check it manually step by step.
用于仿形1 /构建和泄漏检测仪开始。然后探索当前分配的对象,找到您想要的对象(您可以按名称对它们进行排序)并查看其保留/释放历史记录。请注意,保留计数对 ARC 不是很有帮助。您必须逐步手动检查它。
Try to comment all the code which could be the source of leak and then uncomment it step by step.
尝试注释所有可能成为泄漏源的代码,然后逐步取消注释。
2/ Put a NSLog
into your init
and into your dealloc
to watch when the object is created and destroyed.
2/在创建和销毁对象时,将 aNSLog
放入您的init
并放入您的dealloc
以观察。
3/ Don't look only to property definitions, watch if property setters are implemented manually. I found a problem in my friends' project looking like this:
3/ 不要只看属性定义,要注意属性设置器是否是手动实现的。我在朋友的项目中发现了一个问题,如下所示:
@property (weak, nonatomic) id<...> delegate;
@interface ... {
id<...> _delegate;
}
@synthesize delegate = _delegate;
- (void)setDelegate(id<...>)delegate {
_delegate = delegate; //with ARC this retains the object!
}
回答by zenchemical
This solution was somewhat helpful for me. It basically uses method swizzling to tricks the ARC compiler into thinking you're not overriding retain and release.
这个解决方案对我有点帮助。它基本上使用方法 swizzling 来诱使 ARC 编译器认为您没有覆盖保留和释放。
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class cls = [self class];
// When swizzling a class method, use the following:
// Class class = object_getClass((id)self);
SEL originalSelector1 = NSSelectorFromString(@"retain");
SEL swizzledSelector1 = NSSelectorFromString(@"myretain");
SEL originalSelector2 = NSSelectorFromString(@"release");
SEL swizzledSelector2 = NSSelectorFromString(@"myrelease");
Method originalMethod1 = class_getInstanceMethod(cls, originalSelector1);
Method swizzledMethod1 = class_getInstanceMethod(cls, swizzledSelector1);
Method originalMethod2 = class_getInstanceMethod(cls, originalSelector2);
Method swizzledMethod2 = class_getInstanceMethod(cls, swizzledSelector2);
BOOL didAddMethod1 =
class_addMethod(cls,
originalSelector1,
method_getImplementation(swizzledMethod1),
method_getTypeEncoding(swizzledMethod1));
if (didAddMethod1) {
class_replaceMethod(cls,
swizzledSelector1,
method_getImplementation(originalMethod1),
method_getTypeEncoding(originalMethod1));
} else {
method_exchangeImplementations(originalMethod1, swizzledMethod1);
}
BOOL didAddMethod2 =
class_addMethod(cls,
originalSelector2,
method_getImplementation(swizzledMethod2),
method_getTypeEncoding(swizzledMethod2));
if (didAddMethod2) {
class_replaceMethod(cls,
swizzledSelector2,
method_getImplementation(originalMethod2),
method_getTypeEncoding(originalMethod2));
} else {
method_exchangeImplementations(originalMethod2, swizzledMethod2);
}
});
}
-(id)myretain {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
NSLog(@"tracking retain now %d",(int)[self performSelector:NSSelectorFromString(@"retainCount")]);
SEL selector = NSSelectorFromString(@"myretain");
return [self performSelector:selector withObject:nil];
#pragma clang diagnostic pop
}
-(id)myrelease {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
NSLog(@"tracking release now %d",(int)[self performSelector:NSSelectorFromString(@"retainCount")]);
SEL selector = NSSelectorFromString(@"myrelease");
return [self performSelector:selector withObject:nil];
#pragma clang diagnostic pop
}
}
回答by Vimal Venugopalan
If you are using ARC you would never get the option to add retain,
如果您使用的是 ARC,您将永远无法添加保留选项,
and if you have converted the project to ARC using below option, you would be prompted with error
如果您已使用以下选项将项目转换为 ARC,您将收到错误提示
If you have set the property as strong
, then you should allocate the object once through the whole project e.g. self.yourobject = [[NSMutableArray alloc]init];
. There is no shortcut for this.
如果您已将属性设置为strong
,那么您应该在整个项目中分配一次对象,例如self.yourobject = [[NSMutableArray alloc]init];
。这没有捷径可走。