我的项目中有手动参考计数。另外,还有很多多线程。
一些属性不是线程安全的。 :(
我只有一个关于导致崩溃的原因的假设:某些对象被过分释放(?)。
我添加了自动UI测试(Appium
),但它们仍无济于事。
另外,我已经为Zombies
进行了配置-一切正常。
另外,我尝试了Xcode的静态分析器(Product -> Analyze
),虽然有很多警告,但是似乎都没有引起此类崩溃的原因(我看过警告Incorrect decrement of reference count not owned at this point
)。
我用MRC创建了一个测试项目,并添加了以下代码:
- (void)testAssumptions {
//@autoreleasepool
{
[self overReleaseNilValue];
[self overReleaseNotNilValue];
}
}
- (void)overReleaseNilValue {
NSIndexPath* path = [[NSIndexPath alloc] initWithIndex:42];
[path release];
[path release];
}
- (void)overReleaseNotNilValue {
NSIndexPath* path = nil;
[path release];
[path release];
}
在启用自动释放池或没有池的情况下,两次释放对象都不会崩溃。
所以我的问题是:
1.除了释放已释放的对象之外,此类崩溃的另一个原因是什么?
2.是否有办法增加重现这种崩溃的可能性?例如。一些环境变量,从而减少了对不安全代码的某些自动释放池容忍度?还是其他一些自动释放池?
3.为什么我的测试项目代码不会崩溃?
任何评论都将受到赞赏。
答案 0 :(得分:2)
此时尚未拥有的引用计数递减不正确
这绝对是探索的警告。几乎可以肯定,您至少会指出一个错误。
您的测试项目实际上并没有测试任何东西(我相信它们也被反向命名)。无法保证过度释放值会导致崩溃。 overReleaseNotNilValue
是明确定义的行为,绝对不会崩溃(将消息发送到nil
不会执行任何操作)。 overReleaseNilValue
是未定义的行为。我还没有深入研究它,但是我希望NSIndexPath
用带标记的指针实现,如果您过度释放它们,则不会崩溃。
未定义是未定义。这并不意味着崩溃。过度释放值可以做任何事情。如果幸运的话,它会崩溃的。...
此外,还有很多多线程。一些属性不是线程安全的。
我希望这是间歇性问题的核心。我从事过此类项目。解决方案是解决问题。您将不知道哪个特定问题是导致崩溃的原因。您可能永远不会知道。您仍然必须修复所有问题。这将需要一些时间,但是您必须使代码成为线程安全的,否则它的行为是不确定的。
关于调试,您将需要按顺序执行以下操作:
打开“运行时清理”选项(在“方案”编辑器中的“运行”,“诊断”下)。您尤其希望为此使用Thread Sanitizer。
清除所有静态分析器警告。如果他们中有人说您的内存管理有误,请必须清除它们。系统从字面上告诉您问题出在哪里。不要忽略它。
清除所有警告。您的项目中应该有零个警告。如果有很多“错误”警告,那么您将永远看不到真正的警告,告诉您问题出在哪里。消除所有警告。
我花了8个月的时间来消除一个专家开发人员编写的,写得很好并且几乎没有线程的项目中罕见的过发布崩溃。这可能需要很多时间。您必须清除所有问题。仅仅一个不正确的发行版本就足以使程序随机崩溃。