为啥我在 NSTimer 选择器中得到 EXC_BAD_ACCESS?

Posted

技术标签:

【中文标题】为啥我在 NSTimer 选择器中得到 EXC_BAD_ACCESS?【英文标题】:Why am I getting a EXC_BAD_ACCESS in a NSTimer selector?为什么我在 NSTimer 选择器中得到 EXC_BAD_ACCESS? 【发布时间】:2010-05-27 14:06:49 【问题描述】:

我遇到了一个很奇怪的问题。为了简短起见,我将编写一些伪代码:

init: create a dictionary and insert n elements.
      create a "repeat timer" and add it to the currentRunLoop using the timerRefresh selector.

timerRefresh: using a list of keys, find the items in the dictionary
              if the item exists -> call a function

所以,由于未知原因,我得到了一个 EXC_BAD_ACCESS:

    [item function];

但是我追踪了从字典项目中得到的地址,没关系。字典中项目的引用计数仍然是 1。字典中的项目的 release, dealloc 没有被调用。一切似乎都很好。此外,更糟糕的是,它适用于某些项目。

所以,我想知道是否存在线程问题?还是其他什么晦涩难懂的东西?

调用栈非常简单:

#0  0x93e0604b in objc_msgSend_fpret
#1  0x00f3e6b0 in ??
#2  0x0001cfca in -[myObject timerRefresh:] at myObject.m:000
#3  0x305355cd in __NSFireTimer
#4  0x302454a0 in CFRunLoopRunSpecific
#5  0x30244628 in CFRunLoopRunInMode
#6  0x32044c31 in GSEventRunModal
#7  0x32044cf6 in GSEventRun
#8  0x309021ee in UIApplicationMain
#9  0x000027e0 in main at main.m:14

因此,我们将不胜感激任何建议。

--- 编辑 #1 ---

@Laurent:这是我重写实际值以匹配我的示例的错字。 (固定)

@Jeremy:我会尝试发布一些代码来提供帮助。代码已经简化。

定时器初始化+刷新功能:

_refreshTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:5] interval:5
                                 target:self selector:@selector(onTimerRefresh:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_refreshTimer forMode:NSDefaultRunLoopMode];

//...

 (void)onTimerRefresh:(NSTimer*)theTimer 
      // the actual code is here. I will rewrite it so it's simpler:
     for (MyKey key in keys) 
         MyObject* object = [dictionary objectForKey:key];
         if (object)
             [object function];
     
 

我希望它更清楚一点。

是的,我已经在我的“函数”中评论了所有内容,看起来它没有崩溃。我会让它再运行一点,但我没有在那个函数中做任何特别的事情(与内存相关)。只是更新一些枚举值。

--- 编辑 #2 ---

@Laurent:你对 callstak 的看法是对的,我犯了一个巨大的错误。它应该是计时器方法而不是函数。我只是修复它。对不起这个错误。但仅供参考,方法签名是:

- (bool)update;

【问题讨论】:

对“function”方法的调用与存在“functionm:”的堆栈跟踪不匹配。可以吗?你也可以发布一些相关的代码吗? @Laurent +大约一百万用于“发布一些相关代码” @AngeDeLaMort:一些问题:“timerRefresh”选择器是什么意思? NSTimer 上没有这样的选择器。您的堆栈跟踪中没有 timerRefresh 。您从哪里获得密钥列表?请在运行循环中发布定时器初始化和调度的代码以及定时器触发时会发生什么。 你能发布“函数”方法的定义吗?从堆栈跟踪中,它需要一个参数,但您没有传递一个。 定时器激活时字典是否会改变? 【参考方案1】:

我想我终于找到了问题所在。在“更新”方法中

- (bool)update 
    // ...
    NSDate* now = [NSDate dateWithTimeIntervalSinceNow:0];
    NSTimeInterval interval = [now timeIntervalSinceNow] - [creation timeIntervalSinceNow];
    //...

问题是我没有在 init 中保留日期(创建)。我真的不明白为什么对象会“损坏”,但我认为调试器应该指向该变量而不是函数调用...

我会让应用程序运行一段时间,看看崩溃是否消失。

感谢您的帮助。

【讨论】:

如果你想得到现在的日期,你可以做now = [NSDate date];

以上是关于为啥我在 NSTimer 选择器中得到 EXC_BAD_ACCESS?的主要内容,如果未能解决你的问题,请参考以下文章

为啥日期选择器中的日期格式没有改变?

为啥 jQuery 3 不能识别属性选择器中的“#”字符?

为啥我在这个迭代器中遇到分段错误?

为啥 jQuery 在选择器中链接 .attr() 时只选择一个元素?

为啥我在设计查看器中的字体在 Android Studio 中是模糊的?

为啥我在探查器中获得的 C++ 运行时间不准确?