Confusation de codage exception dans nStextStorage
-
29-10-2019 - |
Question
J'ai une sous-classe NSDocument pour un éditeur de texte simple (en utilisant le nouveau modèle d'application basé sur le document de Lion, avec peu de personnalisations), et je rencontre un bogue étrange chargeant le contenu du fichier dans le stockage de texte.
Voici mon code:
- (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];
}
Le bug se produit lorsque je:
- Exécutez l'application dans Xcode (comme une construction de débogage)
- Ouvrez n'importe quel document
- quittez l'application (sans fermer le document)
- Exécutez à nouveau l'application à partir de xcode
Il s'écrase -replaceCharactersInRange:withString:
avec "Impossible de convertir les octets dans la chaîne 0x10004d430 en _NSCStringeNcoding".
Mais ça ne se produit que sur chaque deuxième Lancement de l'application (un troisième lancement ne se bloquera pas, et il sera Rouvrir automatiquement le document qu'il s'est écrasé en essayant d'ouvrir la fois précédemment). Cela ne se produit également que lorsque j'exécute l'application à partir de Xcode. Les versions de libération ne se sont jamais écrasées au lancement.
J'ai pensé que ce pourrait être un problème d'encodage avec le système de sauvegarde automatique, mais il se bloque même lorsque je commençai ce code et que je charge simplement @ "Hello World" dans la vue texte (comme indiqué dans le code ci-dessus). De même, le commentaire NSLog()
ne montre rien de bizarre. Le stockage de texte est valide (chargé à partir du fichier XIB), la longueur de stockage de texte est 0 et le contenu de texte est le contenu du fichier ouvert.
--- ÉDITER ---
J'ai appris que ce problème est lié d'une manière ou d'une autre au com.apple.security.app-sandbox
droit. Si les droits / bac à sable sont activé, puis mon application ne fait pas crash. Si les droits ou la fonction application-sandbox sont désactivé, puis mon application se bloque à chaque deuxième lancement en essayant de restaurer des documents ouverts précédemment.
Je ne l'avais remarqué que lorsqu'il faisait une construction / exécution à partir de l'intérieur de Xcode, car c'était ma seule configuration de construction avec le bac à sable désactivé.
--- /ÉDITER ---
Quelqu'un a-t-il une idée? L'exception complète suit et le code source complet est sur 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
)
La solution 3
Cela semble avoir été un bug dans OS X 10.7 (Lion). Avec des modifications zéro à mon code, le crash ne se produit pas sur OS X 10.8 (lion de montagne) respecté à Xcode 4.4.1.
Autres conseils
J'avoue que cette question m'a perplexe pendant un certain temps. Je pense que j'ai enfin trouvé un repro, cependant.
En regardant à travers le Netteté code qui émule ce comportement, J'ai trouvé le code source suivant:
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;
}
...
De toute évidence, ce code n'est pas un à un avec votre message d'erreur. Cependant, Je le note à partir de votre erreur de repro:
reason: 'Unable to convert bytes in string 0x10004d430 to
_NSCStringEncoding'
Bien, Nous savons tous ce qu'est une chaîne C, et si vous utilisez la mauvaise méthode d'encodage (par exemple, large où ASCII est attendu ou vice versa), vous vous retrouverez exactement avec ce problème. Ainsi: Avez-vous essayé de varier ASCII et de larges types de données dans votre application pour résoudre ce problème?
En raison de la fréquence de ce comportement, cela indique très probablement qu'il s'agit d'un cas géré par le bac à sable d'application. Cependant, je ne trouve pas encore de documentation à cet effet. Cela devrait être quelque chose explicitement noté par sandboxd
, comme je me suis levé dans la question Errata.
J'ai eu la même exception le 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
)
J'utilisais NSTextStorage
dans applicationWillFinishLaunching
. J'ai déplacé ça applicationDidFinishLaunching
Et ça marche bien.