【问题标题】:NSDateFormatter crashes when used from different threadsNSDateFormatter 在不同线程中使用时崩溃
【发布时间】:2011-06-24 02:42:01
【问题描述】:

NSDateFormatter 不断发生随机、奇怪的崩溃。相关的堆栈跟踪是:

Program received signal:  “EXC_BAD_ACCESS”.
#0  0x00000005 in ?? ()
#1  0x0213e3c3 in udat_parse ()
#2  0x01d4e1ca in CFDateFormatterGetAbsoluteTimeFromString ()
#3  0x01d4e225 in CFDateFormatterCreateDateFromString ()
#4  0x003e2608 in getObjectValue ()
#5  0x003e2921 in -[NSDateFormatter getObjectValue:forString:errorDescription:] ()
#6  0x003e21cd in -[NSDateFormatter dateFromString:] ()

日期格式化程序仍在内存中(即未释放或损坏)。我唯一能想到的是崩溃时的字符串不符合格式,但我怀疑这会使格式化程序完全崩溃。 (事先检查格式并非易事)。

有什么想法吗?

【问题讨论】:

    标签: ios objective-c multithreading nsdateformatter exc-bad-access


    【解决方案1】:

    感谢之前的回答者。

    这不是内存问题。原来是同步问题。 NSDateFormatters 不是线程安全的;有一个后台线程试图同时使用相同的格式化程序(因此具有随机性)。

    希望这对将来的某人有所帮助!

    【讨论】:

    • 谢谢帮助我:D 同样的问题,只是随机发生,非常感谢。
    • 我确保每个线程都访问自己的 NSDataFormatter。如果您不担心争用,您可以在使用它的代码周围添加@synchronized(dateFormatter) { ... }
    • 请注意,在格式化程序的大部分访问代码周围放置@sync 后,我仍然看到同样的问题,但不是创建它的代码。因此,您可能想要在类上同步创建代码,然后在格式化程序上同步以设置/使用它。我只是决定重新创建格式化程序,而不是重新使用对象。毫无疑问,我的性能受到了影响,但我宁愿遇到这种情况也不愿崩溃。
    • @Jason:好点子。在我的情况下,保证创建是单线程的。根据对性能的影响,您是否获得了显着影响是值得商榷的,因为您可能会避免线程争用对性能造成更严重的影响。
    • JFYI..从 iOS 7 开始,NSDateFormatter 是线程安全的。 developer.apple.com/documentation/foundation/nsdateformatter
    【解决方案2】:

    另一个解决方案是序列化使用NSDateFormatters 或任何其他非线程安全对象的代码的执行。使用 Grand Central Dispatch,您可以将代码推送到 main_queue:

    dispatch_async(dispatch_get_main_queue(), ^(void){
      [some_object some_message];
    });
    

    或者使用私有队列来达到同样的效果:

    dispatch_queue_t dispatch_queue = dispatch_queue_create("com.MyApp.serializer",NULL);
    dispatch_async(dispatch_queue, ^(void){
      [some_object some_message];
    });
    

    【讨论】:

    • 经过性能测试,在我的(简单)实现中,这个解决方案的速度比使用线程本地存储快两倍。性能测试从多个线程调用stringFromDate:
    【解决方案3】:

    当您使用任何已释放的对象时,将发生 EXCBADACCESS... 尝试使用 NSZombie.. 这是一种查找 EXCBADACCESS 发生位置的简单方法...它将指定哪个方法在哪里以及哪个对象被释放

    查看此链接http://www.markj.net/iphone-memory-debug-nszombie/

    【讨论】:

    • EXC_BAD_ACCESS 不仅发生在已释放的对象上。这意味着任何错误的内存访问(如段错误!)。当然,在大多数情况下,iphone 内存问题是过度释放,但在这种情况下,它被证明是一个同步问题:指针被不同的线程修改,导致取消引用虚假指针。
    【解决方案4】:

    我敢打赌,你传递给日期格式化程序的字符串被过度释放了。

    【讨论】:

    • 我检查了很多很多次。格式化程序和字符串都没有过度释放。原来是同步问题!
    【解决方案5】:

    我在使用 _sigtramp 时遇到了奇怪的崩溃,这导致应用程序看起来被锁定但仍在屏幕上 - 完全阻碍了真正的根本原因。

    事实证明,我们确实引入了多线程数据解析,它与试图使用 NSDateFormatter 解析日期的主 GUI 线程发生冲突。

    围绕 NSDateFormatter formatDate 调用进行一些同步解决了这些问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-12
      相关资源
      最近更新 更多