我的项目中有手动引用计数。此外,还有很多多线程。
一些属性不是线程安全的。 :(
关于这次崩溃的原因,我只有一个假设:某些对象被过度释放(?)。
我已经添加了自动化 UI 测试 (Appium
),但它们还没有帮助。
此外,我还为 Zombies
进行了概要分析 - 一切似乎都正常。
此外,我已经尝试过 Xcode 的静态分析器( Product -> Analyze
),有很多警告,但似乎没有一个是导致这种崩溃的原因(我看过警告 此时不拥有的引用计数的不正确减少
)。
我用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. 为什么我的测试项目代码没有崩溃?
非常感谢任何评论。
最佳答案
Incorrect decrement of reference count not owned at this point
这绝对是探索的警告。它几乎肯定会指向您至少一个错误。
您的测试项目实际上并没有测试任何东西(我相信它们也是倒着命名的)。没有 promise 过度释放一个值会导致崩溃。 overReleaseNotNilValue
是定义明确的行为,绝对不会崩溃(发送消息到 nil
什么都不做)。 overReleaseNilValue
是未定义的行为。我没有深入研究它,但我希望 NSIndexPath
是用标记指针实现的,如果你过度释放它们,它不会崩溃。
未定义是未定义的。这并不意味着崩溃。过度释放一个值可以做任何事情。如果你幸运的话,它会崩溃....
Also, there's a lot of multi-threading. Some of the properties are not thread-safe.
如果它是间歇性的,我希望这是您问题的核心。我从事过这样的项目。解决方案是解决问题。您不会知道是哪个具体问题导致了崩溃。你可能永远不知道。您仍然必须修复它们。这将需要一些时间,但您必须使代码线程安全,否则它的行为是未定义的。
关于调试,您需要按顺序执行以下操作:
打开运行时清理选项(在方案编辑器、运行、诊断下)。为此,您尤其需要 Thread Sanitizer。
清除所有静态分析器警告。如果其中任何一个说您的内存管理有误,您必须清除它们。该系统实际上是在告诉您问题出在哪里。不要忽视它。
清除所有警告。您的项目中应该有零警告。如果有很多“错误”警告,那么您将永远看不到真正的警告,告诉您问题出在哪里。消除所有警告。
我花了 8 个月的时间消除了一个由专家开发人员编写且几乎没有线程的精心编写的项目中罕见的过度发布崩溃。这可能需要很多时间。你必须清除每一个问题。一次错误的发布就足以让程序随机崩溃。
关于ios - 如何重现罕见的 "_CFAutoReleasePoolPop"崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58597706/