Comment " releaser " la mémoire après un CGContextDrawImage ?

Hello les Cocoacafé,


Cela fait plusieurs heures que je tente - en vain - de releaser la mémoire occupée par un CGContextDrawImage dont voici le code : 



        CGSize SourceSize = CGSizeMake(ImageSource.size.width, ImageSource.size.height);
        UIGraphicsBeginImageContext(SourceSize);
        CGContextRef CtxRef = UIGraphicsGetCurrentContext();
        CGContextTranslateCTM(CtxRef, SourceSize.width / 2.0f, SourceSize.height / 2.0f);
        CGContextRotateCTM(CtxRef, M_PI/2);
        CGContextScaleCTM(CtxRef, 1.0f, -1.0f);
        
        CGContextDrawImage(CtxRef, CGRectMake(-ImageSource.size.width / 2.0f,
                                              -ImageSource.size.height / 2.0f,
                                              ImageSource.size.width,
                                              ImageSource.size.height),
                           ImageSource.CGImage);
        
        UIImage *ImageCible = UIGraphicsGetImageFromCurrentImageContext();
        CGContextRelease(CtxRef);
        UIGraphicsEndImageContext();

Je pensais que ARC s'en chargeait ... mais non ... j'ai essayé un @autoreleasespool {} ... sans succès ... des idées / solutions ?


Bien à  vous,


OldNick


 


 


 


Réponses

  • Si mes souvenirs sont bon, tu n'as pas besoin de releaser le contexte graphique, ARC ou pas ARC. Il est sensé disparaitre lors de l'appel à  UIGraphicsEndImageContext().

  • Comment tu sais qu'il est pas release ?

    ApreÌ€s  j'aurai tendance à  mettre CGContextRelease(CtxRef) après UIGraphicsEndImageContext().


     


    À tenter.


  • Merci Draken et Pyroh pour vos réponses ... 


     


    Je sais qu'il n'est pas release via le Debug Navigator / Memory (et confirmé sous Instruments / Allocations) ... et si je le shunte, je n'ai pas ce "pic" de mémoire ....donc c'est bien le CGContextDrawImage et/ou son context qui ne disparaissent pas ....


     


    --> Pyroh : j'ai mis le CGContextRelease après UIGraphicsEndImageContext .... aucun changement ... :'(

  • De mémoire, tout ce qui est CF/CG, il faut faire des CG(ZzZ)Release() uniquement s'il y a eu des CG(ZzZ)Create().


    Concernant la libération de la mémoire en soit, tu as un leak ?


  • --> Larme : je n'ai pas de leak ... mais un heap qui ne cesse d'augmenter ...jusqu'à  atteindre 180 MB ! Je tente par tous les moyens de releaser tout ce que ARC ne fait pas (et qu'il devrait faire d'ailleurs ...) ... notamment j'ai constaté que les UIImageView sur lesquelles on applique des CABasicAnimation ne sont pas systématiquement releasées au changement de vue ...


  • MalaMala Membre, Modérateur
    Je ne vois pas de leak dans ce code. Par contre, vire ton CGContextRelease(). Il n'a rien à  faire ici car tu n'as pas créé le context. Dans ton cas, si je comprends bien la logique sous iOS, c'est UIGraphicsBeginImageContext() qui te génère le contexte courant. Ton appel à  UIGraphicsEndImageContext() suffit.

     

    Est-ce que Instrument t'indique un vrai leak? Ce n'est pas parce que tu montes en mémoire que tu leak forcément. Cela peut venir de caches internes au contexte courant que tu manipules et qui ne sont pas forcément libérés pour des questions d'optimisation de performance. En tous les cas c'est un truc courant sur OSX donc ce serait logique qu'il en soit de même sous iOS.

  • --> Mala : tu ne vois pas de leak dans mon code ... car je n'en ai pas. En revanche, le Debug Navigator / Memory m'indique une consommation croissante qui, si sur un 6s n'est pas grave (quoique), sur iPod 5th génération ou un 4s, finit par faire planter mon app'. Et puis par principe, j'aime coder de manière propre et ne pas laisser trainer en mémoire ce qui est inutile ...


  • L'occupation mémoire croissante provient peut-être d'ailleurs, par exemple une mauvaise libération de tes images.

  • MalaMala Membre, Modérateur

    En tout état de cause la fuite ne vient pas de ce que tu nous donne à  lire.


     


    Deux pistes à  fouiller dans ton projet:


    - retain mutuelles entre deux classes à  toi. A et B se font référence avec un attribut strong et du coup ARC ne libère jamais personne.


    - mauvais usage d'un NSTimer qui est aussi un cas courant menant très facilement à  une fuite.


  • --> Mala : merci pour ton avis. Pour info j'ai  réussi à  "isoler" les lignes de codes qui provoquent l'accroissement de mémoire .. ce sont celles que j'ai précisées dans mon 1er post donc je ne pense pas qu'il y ait de retain mutuel. De même je n'utilise pas de NSTimer.


     


    --> Draken : pour "libérer" mes images, je les initialize à  "nil" ... est-ce correct ?  


  • C'est quoi le contexte de ton code ? Tu fais quoi de ces images ?


  • --> Pyroh : j'ai besoin de "cropper" une image qui a été préalablement "scaled" et "rotated" ...l'image obtenue me sert ensuite dans une "magnify view" (loupe) ... pour des besoins de précision, mon "crop" doit être dans la définition native de l'image ... 


  • DrakenDraken Membre
    avril 2016 modifié #14

    Tu devrais jeter un oeil sur la fonction resize de la Bible du Développeur iOS (appelée aussi les mémoires d'un aligator) :


     


    https://github.com/AliSoftware/UIImage-Resize


     


    Tu verras qu'il ne release pas le contexte graphique, se contentant d'appeler UIGraphicsEndImageContext().


  • --> Draken  : merci pour ce conseil biblique ! Je vais y jeter un oeil ...


Connectez-vous ou Inscrivez-vous pour répondre.