如何再现罕见的“ _CFAutoReleasePoolPop”崩溃?

问题描述 投票:0回答:1

我正在尝试重现此类崩溃:enter image description here

我的项目中有手动参考计数。另外,还有很多多线程。一些属性不是线程安全的。 :(我只有一个关于崩溃原因的假设:某些对象被过度释放(?)

我已经添加了自动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.为什么我的测试项目代码不会崩溃?

高度评价任何评论。

ios objective-c core-foundation nsautoreleasepool manual-retain-release
1个回答
1
投票

此时尚未拥有的不正确的引用计数递减

这绝对是警告探索。几乎可以肯定,您至少会指出一个错误。

您的测试项目实际上没有测试任何东西(我相信它们也被反向命名)。无法保证过度释放值会导致崩溃。 overReleaseNotNilValue是明确定义的行为,绝对不会崩溃(将消息发送到nil不会执行任何操作)。 overReleaseNilValue是未定义的行为。我还没有深入研究它,但是我希望NSIndexPath将使用带标记的指针实现,如果您过度释放它们,则不会崩溃。

未定义是未定义的。这并不意味着崩溃。过度释放值可以做任何事情。如果幸运的话,它会崩溃的。...

此外,还有很多多线程。一些属性不是线程安全的。

我希望这是间歇性问题的核心。我从事过此类项目。解决方案是解决问题。您将不知道哪个特定问题是导致崩溃的原因。您可能永远不会知道。您仍然必须修复所有问题。这将需要一些时间,但是您必须使代码成为线程安全的,否则其行为是不确定的。

关于调试,您将需要按顺序执行以下操作:

  • 启用运行时清理选项(在方案编辑器的“运行”,“诊断”下)。您尤其希望为此使用Thread Sanitizer。

  • 清除所有静态分析器警告。如果它们中的任何一个表明您的内存管理有误,请have清除它们。系统从字面上告诉您问题出在哪里。不要忽略它。

  • 清除所有警告。您的项目中应该有零个警告。如果有很多“错误”警告,那么您将永远看不到真正的警告,告诉您问题出在哪里。消除所有警告。

我花了8个月的时间来消除一个专家开发人员编写的,写得很好且几乎没有线程的项目中罕见的过发行崩溃。这可能需要很多时间。您必须清除所有问题。只有一个不正确的发行版本足以使程序随机崩溃。

© www.soinside.com 2019 - 2024. All rights reserved.