[iPhone SDK][Bug] Cash a l'utilisation de stringByAppendingString de NSString
Bonjour,
Débutant en cocoa je viens solliciter votre aide a propos d'un bug récurant que je ne parviens a résoudre.
Je travaille actuellement sur le bout de code tout simple suivant :
Celui-ci est placé dans un outlet tout bête appelé depuis un bouton dans l'interface de l'iPhone.
Hors au bout d'un nombre variable de pression de celui-ci mon appli plante inexplicablement Oo
Pourriez vous m'éclairer sur un possible mauvais choix de fonction ou bien pensez vous que le bug proviens du framework d'Apple?
Débutant en cocoa je viens solliciter votre aide a propos d'un bug récurant que je ne parviens a résoudre.
Je travaille actuellement sur le bout de code tout simple suivant :
s_Buffer = [s_Buffer stringByAppendingString: @"1"];
Celui-ci est placé dans un outlet tout bête appelé depuis un bouton dans l'interface de l'iPhone.
Hors au bout d'un nombre variable de pression de celui-ci mon appli plante inexplicablement Oo
Pourriez vous m'éclairer sur un possible mauvais choix de fonction ou bien pensez vous que le bug proviens du framework d'Apple?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Moralité ne pas suivre la doc d'Apple mais les exemples fournis >:D
Reste a savoir pourquoi plante Oo
stringByAppendingString retourne une chaà®ne dite autorelease. Son existence n'est donc garantie que dans le cadre de ta méthode.
avec une méthode init... la c'est toi qui gère la libération mémoire. Donc effectivement ça ne plante plus. Par contre vu ton code c'est la fuite mémoire assurée...
Il faudrait peut-être juste commencer par le début de la doc Apple pour le coup. :P
Ceci dit, bienvenue sur le forum.
http://74.125.39.104/search?q=cache:DI6ugSF78OMJ:www.projectomega.org/article.php?lg=fr&php=oreilly_cocoa9&p=1+objective-c+cgestion+mémoire&hl=fr&ct=clnk&cd=1
Cela devrait t'apporter les explications qu'il te faut.
Sinon pour project-omega ce n'est pas bien grave, j'ai actuellement comme livre de chevet Cocoa par la pratique, je vais relire le passage sur la gestion de la mémoire.
Par contre une chose, bien que je n'avais pas remarqué que stringByAppendingString soit un autorelease, je sauvegarde bien le contenus retourné par la fonction dans une string avant que celle-ci ne s'efface non? Car s_Buffer est un pointeur de type NSString. Ou bien je suis complètement a coté de la plaque, j'ai un doute sur ma vision de la chose d'un coup :-\\ ?
Une dernière chose, dois-je rajouter un petit release quelque part pour éviter une fuite de mémoire avec l'utilisation de :
Car en effet si a chaque fois une sous chaine de mon résultat en cour ce forme est est stocké pour rien, la fuite de mémoire est assurée :crackboom:-
Effectivement, il y a un problème de compréhension. Tu n'aurais pas aussi mangé du Java à tour de bras? Plus sérieusement, s_Buffer est un pointeur (même concept qu'en C ou C++). L'affectation = ne fait que stocker l'adresse de ton objet dans ton pointeur. Maintenant, rien ne t'empêche de le libérer ( [s_Buffer release] ) pour autant ton pointeur restera sur cette zone mémoire mais ne sera plus accessible. Si tu souhaite conserver un objet autorelease, il te faut faire un retain dessus. Du coup, tu reviens à ta seconde situation ou on retombe sur un problème de fuite.
On en vient effectivement là . Donc le problème c'est que initWithFormat va créer un nouvel objet. Comme tu l'affectes dans s_Buffer, si celui pointait vers un précédent objet, tu vas en écraser l'adresse et donc perdre le lien vers cet objet. Comment faire alors?
Solution 1: Passer par un pointeur "tampon"
Bien, si cette méthode fonctionne, elle n'est pour le coup ni élégante (beaucoup de code pour pas grand chose) ni efficace (on passe notre temps à recréer des objets avec stringByAppendingString). Si tu regardes d'un peu plus prêt les classes à ta disposition en Obj-C, tu vas découvrir que la plupart d'entre elles on un équivalent "mutable": NSMutableString, NSMutableArray, NSMutableDictionary, etc...
La méthode 2 consiste donc à préférer un objet modifiable qui correspond bien mieux à ton besoin ici:
Contrairement au premier code, ici s_Buffer sera toujours le même objet donc plus besoin de quoi que ce soit d'autre.
En espérant t'avoir un peu éclairer. Prends le temps de bien appréhender tout ça. Cocoa par la pratique est un très bon ouvrage. Si tu as des questions n'hésites pas.
Utiliser la notion d'autorelease au lieu d'un tampon:
Cette méthode est relativement light en terme de syntaxe. Par contre, on cré toujours un nouvel objet à chaque passe ce qui n'est pas optimal.
Je vais méditer ce ceci et adapter mon code en fonction.
Je t'en donnerais des nouvelles
Merci encore pour ta patience