【问题标题】:EXC_BAD_ACCESS on animationForKey:animationForKey 上的 EXC_BAD_ACCESS:
【发布时间】:2012-04-22 15:15:29
【问题描述】:

我正在尝试使用 Scintilla 组件 的最新功能,它提供了类似 OSX 的文本突出显示效果(黄色动画弹跳框),但我遇到了一个错误,即间歇性弹出:

EXC_BAD_ACCESS

指向这一特定行:

if (layerFindIndicator!=nil)
        if ([layerFindIndicator animationForKey:@"animateFound"])
            [layerFindIndicator removeAnimationForKey:@"animateFound"];

ifs 是我的;以防万一我发现对象 layerFindIndicator 为 nil,或已解除分配或其他...不幸的是,它无济于事...)

layerFindIndicator 似乎是CAGradientLayer 的子类。 (您可能会看到layerFindIndicatorhere 的完整代码)。

既然,我是 Quartz Core 的绝对新手,请给我任何关于如何调试它的提示吗?

【问题讨论】:

  • 我猜 layerFindIndicator` 已经被dealloc'ed 了。该 if 语句不会防止未设置为 nil 的已释放对象。例如寻找你在哪里发布它......
  • @Paul.s 你说得很有道理,但我绝对无法发现对象可能被释放的位置......(这不是我的代码,而是一些新添加的片段这使它成为最新的 Scintilla 版本,所以我很迷茫)。我现在正在尝试在此之前创建对象(因为无论如何都应该创建它),并且它似乎正在工作(到目前为止,就是......)

标签: objective-c cocoa exc-bad-access quartz-graphics cagradientlayer


【解决方案1】:

由于我是 Quartz Core 的绝对新手,请给我任何关于如何调试它的提示吗?

这与 QuartzCore 没有任何关系(至少,我希望不是)——这是一般的 this-object-has-been-killed-before-its-time-how-do-I-find-the -杀手的东西。

在 Xcode 中:

  1. 编辑您当前的方案。
  2. 对于 Profile 操作,将其设置为使用 Debug 构建配置。
  3. 关闭它,然后点击 Profile 命令。

Xcode 将为该操作构建,然后启动 Instruments。

仪器会提示您选择模板;你想要僵尸模板。一旦您选择了它,Instruments 将创建一个跟踪文档并运行您的应用程序。切换到您的应用程序(如果它不是最前面的),然后执行任何导致崩溃的操作。

如果崩溃真的是死物崩溃,僵尸会显示它。你会在 Instruments 的时间线中看到一个标志,上面写着“消息发送到僵尸对象 0xd3c2b1a0”,然后你的程序可能很快就会退出。

在那个标志中有一个小按钮,看起来像这样: ➲ 除了它会是灰色的。点击它。

这会将您带到该对象的历史(实际上是该地址的历史,包括任何以前的对象或从该地址开始的其他分配)。显示您的扩展详细信息窗格(出现在右侧显示堆栈跟踪的那个),然后向下滚动到最后,然后逐步向后(向上)移动,查看发布和自动发布,寻找一个'不平衡对象的分配或保留。

解决方案可能涉及以下一项或多项:

  • 将属性更改为 strongweak 而不是 assign/unsafe_unretained
  • 在您之前没有强烈拥有对象的位置添加属性
  • 如果不清楚您需要执行上述哪一项,或者其中任何一项看起来像是肮脏的 hack,请重新架构一些东西
  • 切换到 ARC 以获取 weak 属性和 __weak 实例变量(当引用的对象死亡时,这两个变量都会自动设置为 nil)并获取被隐式初始化为 nil 的局部变量

但这取决于您在 Instruments 中找到的内容。而且,当然,您的问题(错误的访问权限)也有可能根本不是死对象,以上所有内容都对您没有帮助。

【讨论】:

    【解决方案2】:

    试试这个:

    if (layerFindIndicator!=nil){
        if ([layerFindIndicator animationForKey:@"animateFound"]){
            [layerFindIndicator removeAnimationForKey:@"animateFound"];
        }
    }
    

    同时检查它是否被释放。

    编辑:

    我发现的另一件事是 if 中没有空格。您的代码现在应该如下所示:

    if (layerFindIndicator != nil){
        if ([layerFindIndicator animationForKey:@"animateFound"]){
            [layerFindIndicator removeAnimationForKey:@"animateFound"];
        }  
    }
    

    【讨论】:

    • 虽然我个人会用括号重写 OP 的原始代码 - 这对功能没有影响......
    • 哦,我失败了。我认为这是必须...我想我应该重新阅读我的 Objective C 书。
    • 我自己通常不会这样写(不带括号);我只是为了调试而输入的(当我调试时,我个人并不关心样式......):-)
    • TBH 这是我检查的第一件事,以防出现错误 - 手头有一个快速测试项目或 CodeRunner 总是很方便。 @Dr.Kameleon 我总是尝试编写可靠的代码,因为您永远不知道“原型”代码何时会因为缺乏记忆或时间限制而投入生产。
    • @Paul.s 也很正确......虽然在我(诚然很尴尬)编码时尚有两个阶段:1)写作,2)清理(真的没有意义,我知道;但这几乎是我无能为力.. 大声笑);-)
    猜你喜欢
    • 2011-08-04
    • 1970-01-01
    • 2016-06-23
    • 2015-03-13
    • 2012-03-05
    • 2021-04-02
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多