2009-08-13 5 views
3

Venant d'un contexte Symbian, je suis un peu préoccupé par l'absence apparente de gestion des erreurs dans Cocoa. Cocoa a de nombreuses méthodes qui, d'après ce que je peux voir, n'ont aucun rapport d'erreur et pourtant pourraient échouer.Puis-je faire confiance aux API Cocoa pour ne pas échouer silencieusement, ou dois-je vérifier de manière défensive tout?

Par exemple NSMutableString appendString a un type de retour void et ne lance pas d'exceptions (au moins le documentation n'en mentionne aucun)? Sûrement si j'ajoute une chaîne assez longue alors théoriquement je pourrais manquer de mémoire. Est-il paranoïaque de moi de vérifier la longueur de NSMutableString avant et après l'ajout pour vérifier que l'append a travaillé?

+5

Malheureusement, Breton, votre conseil ne parvient pas à élucider quoi que ce soit –

Répondre

6

Mon test est sur Mac OS X et j'imagine que vous parlez de la plate-forme iPhone. Le fait est que je ne vois pas comment retourner une erreur de la méthode appendString aiderait puisque la plate-forme est à ce point dans un tel état qu'elle ne peut pas satisfaire les requêtes malloc pour votre processus. Pour contourner le problème, vous pouvez probablement utiliser votre propre espace d'adressage et utiliser cette mémoire gérée par processus pour stocker vos chaînes. Je pense que CFString de Carbon (sans frais couplé à NSString) vous permet d'utiliser votre propre allocateur de mémoire.

#import <Foundation/Foundation.h> 

int main (int argc, const char * argv[]) 
{ 
    NSAutoreleasePool * pool = [NSAutoreleasePool new]; 
    NSMutableString * m = [NSMutableString stringWithCapacity:100000]; 

    int i; 
    for(i=0;i<1000000;i++) 
     [m appendString:@"ABCDE..."]; //1400 characters long 
    [pool release]; 
} 



cd:tmp diciu$ ./a.out 
a.out(2216) malloc: *** mmap(size=1220067328) failed (error code=12) 
*** error: can't allocate region 
*** set a breakpoint in malloc_error_break to debug 
[..] 
2009-08-13 16:45:44.163 a.out[2216:10b] *** Terminating app due to uncaught exception  'NSMallocException', reason: 'Out of memory. We suggest restarting the application. If you  have an unsaved document, create a backup copy in Finder, then try to save.' 
2009-08-13 16:45:44.165 a.out[2216:10b] Stack: (
    2494541803, 
    2485014075, 
    2435399864, 
    2494157025, 
    2494172776, 
    2434276628 
) 
Trace/BPT trap 
+0

Merci, diciu, de m'avoir mis sur la bonne voie. Apparemment, une exception * est * levée. Je vais écrire la réponse. –

+0

Malheureusement, les choses ne sont pas si simples pour l'iPhone. J'ai utilisé @trap et @catch avec un code similaire au vôtre, et dans l'émulateur, j'ai attrapé une exception (obsolète!) NSMallocException. Malheureusement, lors du débogage sur l'appareil, je reçois:

 Program received signal: “0”. warning: check_safe_call: could not restore current frame 

+0

Si votre application est susceptible de rencontrer des problèmes de mémoire, vous devez gérer la gestion de la mémoire par vous-même. Vous pouvez ensuite appeler des éléments qui n'écrivent dans votre stockage de mémoire que s'il y a de la place. Dans la vraie vie, je ne pense pas que vous ayez à vous soucier de l'échec d'appendString en raison de l'épuisement de la mémoire. – diciu

2

J'ai modifié le test de code de diciu NSMutableString appendString à l'échec plus rapide et d'essayer d'attraper toutes les exceptions. Voici la section de base:

 
    NSMutableString * m = [[NSMutableString alloc] initWithCapacity:1000]; 
    NSMutableString * n = [[NSMutableString alloc] initWithCapacity:1000]; 
    @try { 
     [m appendString:@"1234567890"]; 
     [n appendString:m]; 
     int i; 
     for(i=0;i<100;i++) { 
      [m appendString:n]; 
      [n appendString:m]; 
     } 
    } 
    @catch (id exception) { 
     NSLog(@"!!Exception"); 
    } 
// @catch (NSException *exception) { 
//  NSLog(@"!!Exception: %@", [exception name]); 
// } 
    @finally { 
     [m release]; 
     [n release]; 
     NSLog(@"Finally..."); 
    } 

J'ai testé sur différentes plates-formes:

Mac OS X 10.5.8 & Xcode 3.1.3 iPhone 3.0 Emulator: Une exception levée (NSException, avec le nom NSMallocException). C'est une bonne nouvelle mais étrange puisque NSMallocException est supposément obsolète.

iPhone 3.0.1: l'application tombe en panne. Les mauvaises nouvelles sont que pour l'iPhone, il semble qu'il n'y a aucun moyen d'attraper cette erreur. La bonne nouvelle est qu'il n'y a pas de point de programmation défensif, puisque toute l'application explose quand même!

J'espère que quelqu'un a une meilleure réponse que celle-ci.

+0

Pour ce que ça vaut sur 10.5.8 i386 4 Go de RAM le code ci-dessus ne se bloque pas, il lance une exception (mémoire insuffisante). – diciu

+0

Merci diciu; tu es plus patient que moi. Quand j'ai testé, je n'ai pas attendu assez longtemps pour attraper l'exception. Je vais corriger mon texte ci-dessus. –

Questions connexes