【问题标题】:Confusing encoding exception in NSTextStorageNSTextStorage 中令人困惑的编码异常
【发布时间】:2011-12-06 22:05:19
【问题描述】:

我有一个简单文本编辑器的 NSDocument 子类(使用 Lion 的新基于文档的应用程序模板,几乎没有自定义),我在将文件内容加载到文本存储时遇到了一个奇怪的错误。

这是我的代码:

- (void)loadTextContentIntoStorage
{
  if (!self.textStorage || !textContentToLoad)
    return;

  ...

  [self.textStorage beginEditing];

//  NSLog(@"storage: %@ length: %lu textContent: %@", self.textStorage, (unsigned long)self.textStorage.length, textContentToLoad);
//  [self.textStorage replaceCharactersInRange:NSMakeRange(0, self.textStorage.length) withString:textContentToLoad];
  [self.textStorage replaceCharactersInRange:NSMakeRange(0, 0) withString:@"hello world"];

  ..

  [self.textStorage endEditing];
}

错误发生在我:

  • 在 Xcode 中运行应用程序(作为调试版本)
  • 打开任何文档
  • 退出应用(不关闭文档)
  • 再次从 Xcode 运行应用程序

它在 -replaceCharactersInRange:withString: 中崩溃,并显示“无法将字符串 0x10004d430 中的字节转换为 _NSCStringEncoding”。

但它只会在应用程序的每 次启动时发生(第三次启动不会崩溃,并且它自动重新打开它尝试打开时崩溃的文档上一次)。它也只发生在我从 Xcode 运行应用程序时。发布版本从未在发布时崩溃。

我认为这可能是自动保存系统的编码问题,但是当我注释掉该代码并将@“hello world”字符串加载到文本视图中时它甚至崩溃(如上面的代码所示)。同样,注释掉的NSLog() 并没有显示任何奇怪的东西。文本存储有效(从xib文件加载),文本存储长度为0,textContent为正在打开的文件的内容。

--- 编辑---

我了解到这个问题在某种程度上与com.apple.security.app-sandbox 权利有关。如果权利/沙盒启用,那么我的应用不会崩溃。如果权利或应用程序沙盒功能被禁用,那么我的应用程序在每次启动尝试恢复之前打开的文档时都会崩溃。

我只注意到它在从 xcode 内部进行构建/运行时崩溃,因为这是我唯一禁用沙盒的构建配置。

--- /编辑---

有人有什么想法吗?完整异常如下,完整源码在github上:https://github.com/abhibeckert/Dux/blob/master/Dux/DuxTextView.m

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Unable to convert bytes in string 0x10004d430 to _NSCStringEncoding'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff84afb286 __exceptionPreprocess + 198
    1   libobjc.A.dylib                     0x00007fff88991d5e objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff84afb0ba +[NSException raise:format:arguments:] + 106
    3   CoreFoundation                      0x00007fff84afb044 +[NSException raise:format:] + 116
    4   Foundation                          0x00007fff835bfae4 copyFromStringToStorage + 262
    5   Foundation                          0x00007fff835bf979 -[NSBigMutableString replaceCharactersInRange:withString:] + 1000
    6   Foundation                          0x00007fff835bc3f7 -[NSConcreteMutableAttributedString replaceCharactersInRange:withString:] + 375
    7   AppKit                              0x00007fff86149e14 -[NSConcreteTextStorage replaceCharactersInRange:withString:] + 81
    8   Dux                                 0x0000000100002f9a -[MyTextDocument loadTextContentIntoStorage] + 1338
    9   Dux                                 0x00000001000022a0 -[MyTextDocument windowControllerDidLoadNib:] + 640
    10  AppKit                              0x00007fff860f1328 -[NSWindowController _windowDidLoad] + 667
    11  AppKit                              0x00007fff860e89a3 -[NSWindowController window] + 109
    12  AppKit                              0x00007fff8615d761 -[NSDocument windowForSheet] + 86
    13  AppKit                              0x00007fff860e82c4 -[NSDocument _shouldShowAutosaveButtonForWindow:] + 50
    14  AppKit                              0x00007fff860e7fbb -[NSWindowController setDocument:] + 237
    15  AppKit                              0x00007fff8629c9b6 -[NSDocument makeWindowControllers] + 139
    16  AppKit                              0x00007fff8615d555 -[NSDocument(NSPersistentUISupport) restoreDocumentWindowWithIdentifier:state:completionHandler:] + 90
    17  AppKit                              0x00007fff8615d4aa -[NSDocumentControllerPersistentRestoration loadedDocument:forAutoID:] + 179
    18  AppKit                              0x00007fff8615cfbe __-[NSDocumentController reopenDocumentForURL:withContentsOfURL:display:completionHandler:]_block_invoke_8 + 187
    19  AppKit                              0x00007fff86148e14 __-[NSDocumentController reopenDocumentForURL:withContentsOfURL:display:completionHandler:]_block_invoke_5 + 163
    20  AppKit                              0x00007fff86148d5f __-[NSDocumentController reopenDocumentForURL:withContentsOfURL:display:completionHandler:]_block_invoke_4 + 697
    21  AppKit                              0x00007fff86148aa1 -[NSDocumentController _openDocumentWithContentsOfURL:usingProcedure:] + 530
    22  AppKit                              0x00007fff8614868d __-[NSDocumentController reopenDocumentForURL:withContentsOfURL:display:completionHandler:]_block_invoke_3 + 242
    23  libdispatch.dylib                   0x00007fff8bbbe8ba _dispatch_call_block_and_release + 18
    24  libdispatch.dylib                   0x00007fff8bbc072a _dispatch_main_queue_callback_4CF + 308
    25  CoreFoundation                      0x00007fff84a904dc __CFRunLoopRun + 1724
    26  CoreFoundation                      0x00007fff84a8fae6 CFRunLoopRunSpecific + 230
    27  HIToolbox                           0x00007fff8852f3d3 RunCurrentEventLoopInMode + 277
    28  HIToolbox                           0x00007fff8853663d ReceiveNextEventCommon + 355
    29  HIToolbox                           0x00007fff885364ca BlockUntilNextEventMatchingListInMode + 62
    30  AppKit                              0x00007fff85ef23f1 _DPSNextEvent + 659
    31  AppKit                              0x00007fff85ef1cf5 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 135
    32  AppKit                              0x00007fff85eee62d -[NSApplication run] + 470
    33  AppKit                              0x00007fff8616d80c NSApplicationMain + 867
    34  Dux                                 0x0000000100001e32 main + 34
    35  Dux                                 0x0000000100001e04 start + 52
    36  ???                                 0x0000000000000003 0x0 + 3
)

【问题讨论】:

  • 可能有内存损坏。您是否尝试过运行 XCode 中可用的内存一致性工具? (构建和分析、僵尸等)
  • 是的,我已经尝试构建和分析,并且启用了僵尸。我也在使用 ARC。
  • 我去拿了你的项目,因为它很吸引人。我启用了涂鸦保护和所有这些,仍然没有任何问题。分析器显示了许多有效的问题,但修复它们并不会影响此问题。
  • 我能想到的唯一想法是,您的应用程序在正确加载文档时会进入某种“状态”,这会影响它在下次运行时的启动(但仅在调试器中的调试中?)。如果它崩溃,它不会执行加载行之后的任何代码。我尝试通过在每次运行的连续行上杀死它来查看它是否是函数中的一行导致它,但如果你这样做它仍然有效。导致问题的原因是应用程序中的其他地方。我希望这会有所帮助!
  • 令人着迷!根据App Sandbox Design Guide,您应该能够通过从控制台运行sandboxd 来询问您的应用程序在沙盒模式下运行时的情况。当您这样做时,您是否看到报告的任何违规行为?

标签: objective-c macos cocoa nstextstorage


【解决方案1】:

我承认,这个问题困扰了我很长一段时间。不过,我想我终于找到了一个复制品。

翻阅GNUstepcode that emulates this behavior,找到如下源码:

if (enc == NSASCIIStringEncoding
    && isByteEncoding(internalEncoding))
    {
      unsigned  i;

      if (bytes > self->_count)
    {
      bytes = self->_count;
    }
      for (i = 0; i < bytes; i++)
    {
      unsigned char c = self->_contents.c[i];

      if (c > 127)
        {
          [NSException raise: NSCharacterConversionException
              format: @"unable to convert to encoding"];
        }
      buffer[i] = c;
    }
      buffer[bytes] = '\0';
      if (bytes < self->_count)
    {
      return NO;
    }
      return YES;
    }
...

显然,此代码与您的错误消息不是一对一的。 然而,我从你的错误重现中注意到了这一点:

reason: 'Unable to convert bytes in string 0x10004d430 to_NSCStringEncoding'

好吧,we all know what a C String is,如果你使用了错误的编码方法(例如,Wide 应该是 ASCII,反之亦然),你最终会遇到这个问题。因此:您是否尝试在应用程序中使用不同的 ASCII 和 Wide 数据类型来解决此问题?

由于这种行为很常见,它很可能表明它是由应用程序沙箱处理的案例。但是,我还找不到有关此效果的文档。这应该是 sandboxd 明确指出的,正如我在问题勘误表中提出的那样。

【讨论】:

  • 嗯,Abhi 还没有回应这是否会导致他遇到问题,但我的赏金即将到期,你的回答是经过深思熟虑的,至少有帮助,所以我会奖励你赏金。
  • 感谢您的帮助,我有空会研究一下。虽然不是很乐观,因为当我将硬编码的@“hello world”字符串常量插入字段时甚至会发生崩溃,而不仅仅是当我从文件中读取字符串时。我的下一个调试想法是,异常不是在谈论我正在 插入 的字符串,而是已经在文本字段中的字符串对象,被新值替换。 Cocoa 的 Auto-Save 可能在那里做一些奇怪的事情?我还没来得及试验。
  • 我很想看看结果如何。我回溯到可以容忍的记录,但可以想象我可以把它扔到 Xcode 中看看会发生什么。我希望它是一个简单的字符编码问题,但 wherewhy 是这里最重要的。
  • 它是仅包含 ascii 字符的可重现文档。即使是已自动保存的空文本文档也会在每次启动时崩溃。但我一定会更新这个问题。只是这是我的一个开源项目,不是有偿工作,而且我现在的一些日常工作编程工作进度落后。
【解决方案2】:

我在 10.9.2 遇到了同样的异常。

 Unable to convert bytes in string 0x60800026cd40 to _NSCStringEncoding
 (
    0   CoreFoundation                      0x00007fff8dec825c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff81de0e75 objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff8dec810c +[NSException raise:format:] + 204
    3   Foundation                          0x00007fff8d94dd2b copyFromStringToStorage + 223
    4   Foundation                          0x00007fff8d94db9e -[NSBigMutableString replaceCharactersInRange:withString:] + 1081
    5   Foundation                          0x00007fff8d94d738 -[NSConcreteMutableAttributedString replaceCharactersInRange:withAttributedString:] + 296
    6   AppKit                              0x00007fff88d7889c -[NSConcreteTextStorage replaceCharactersInRange:withAttributedString:] + 77
    9   myApp                            0x00000001035d3fff myApp + 12287
    10  CoreFoundation                      0x00007fff8de96e0c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    11  CoreFoundation                      0x00007fff8dd8a82d _CFXNotificationPost + 2893
    12  Foundation                          0x00007fff8d8f8e4a -[NSNotificationCenter postNotificationName:object:userInfo:] + 68
    13  AppKit                              0x00007fff88b99cde -[NSApplication finishLaunching] + 440
    14  AppKit                              0x00007fff88b997f3 -[NSApplication run] + 128
    15  AppKit                              0x00007fff88b84783 NSApplicationMain + 940
    16  libdyld.dylib                       0x00007fff81aa65fd start + 1
    17  ???                                 0x0000000000000001 0x0 + 1
)

我在applicationWillFinishLaunching 中使用了NSTextStorage。我已将其移至 applicationDidFinishLaunching 并且工作正常。

【讨论】:

    【解决方案3】:

    这似乎是 OS X 10.7 (Lion) 中的一个错误。对我的代码进行零更改后,在符合 Xcode 4.4.1 的 OS X 10.8 (Mountain Lion) 上不再发生崩溃。

    【讨论】:

    • 我在 OS X 10.9.1 上的 Xcode 5.0.2 中的一个项目中看到了这个问题。我很想知道它是否曾经为你重新出现过?
    • @CharlesA。对我来说它没有重新出现,但也许还有其他方法可以触发相同的症状。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 1970-01-01
    • 2014-10-17
    • 2022-01-21
    相关资源
    最近更新 更多