Objective-C

Mémoire - Concept

Introduction

Nous allons maintenant voir comment est gérée la mémoire sur iOS et OSX. Nous commencerons par expliquer le principe du compteur de référence puis nous verrons comment il a été automatisé. Enfin, nous finirons par une présentation rapide de la gestion de la mémoire avec le CoreFoundation (le noyau de Cocoa).

Compteur de référence

Son principe est simple. Pour chaque référence d'un objet, il existe un compteur. Lorsque l'on alloue cet objet, le compteur est placé à 1. Les méthodes retain et release permettent de modifier la valeur de ce compteur. Retain réalise un + 1 et Release un -1. Dès lors que le compteur passe à 0, l'objet sera détruit.

L'illustration ci-dessous représente le fonctionnement du compteur :

Source : Apple.

Sur iOS, le compteur de référence est la seule solution pour gérer la mémoire. Il n'y a pas de garbage collection. Et sur OSX, le garbage est obsolète depuis OSX 0.8 (Mountain Lion).

Quelques outils très pratiques

XCode, l'outil de développement proposé par Apple, utilise un analyseur syntaxique qui permet de détecter les problèmes de gestion de mémoire.

Grâce à cet outil, on peut savoir si notre objet à un compteur encore supérieur à 1 en sortie de méthode et donc que notre objet ne sera pas désalloué. Globalement cet outil visualise déjà bien l'ensemble des fuites mémoire qu'une application pourrait avoir mais cet analyse reste une analyse du code statique. Pour pousser la recherche, il faut s'orienter vers un autre outil proposé par Apple, Instruments. Cet outil fait une analyse en temps réel de l'application et retourne des informations poussées sur la mémoire, le processeur, ...

Ici, j'ai lancé une analyse sur les possibles fuites mémoire lors du déroulement de l'application :

Mémoire - ARC

Disponible depuis iOS 5 et OSX 10.7 (Lion) sur XCode 4.2, l'Automatic Reference Counting (ARC) gère le compteur de référence de manière automatique. Par une analyse du code, le compilateur insère lui même les retain et realease. Ainsi, plus besoin de réfléchir à comment ou à quel moment il va falloir désallouer un objet, l'ARC le fait pour nous. La charge de temps pour gérer mémoire avec le compteur de référence était de 30% sur le temps total du développement. Ce temps est ainsi économisé pour améliorer l'application ou ajouter de nouvelles fonctionnalités.

Source : Apple.

Cependant, quelques notions supplémentaires permettent d'optimiser cette gestion. Les pointeurs peuvent être spécifiquement alloué avec une force de persistance. Il existe 2 options :

La première option, strong signifie que la portée du pointeur ira au moins jusqu'à la fin de la méthode. Ensuite le pointeur sera désalloué s'il n'a pas été passé en paramètre d'une méthode.

		
NSString * __strong str = @"Youpi";
	    
	  

La deuxième option, weak signifie que la portée du pointeur n'ira pas plus loin que l'instruction. Dans l'exemple ci-dessous, un NSLog(@"%@", str); affichera null.

		
NSString * __weak str = @"Youpi";
	    
	  

Si l'on ne donne pas d'option, le compilateur utilisera la valeur par défaut qui est : __strong.

Il existe d'autres types de référence (__strong qui a une portée dans le bloc de code) qui sont référencés sur le site de Clang dans la section ARC disponible sur ce lien

Mémoire - CoreFoundation

Introduction

CoreFoundation représente la librairie noyau d'Apple, Inc. De ce fait, elle ne dispose pas des mêmes fonctionnalités de gestion de la mémoire. C'est pour cela que la mémoire doit encore être gérée à la main comme nous le verrons dans la suite.

Cas pratique

Dans cet exemple, nous allons créer une chaîne de caractère en utilisant les objets et méthodes du CoreFoundation. Nous allons ensuite augmenter puis diminuer son compteur.

		
CFStringRef str = CFSTR("Hello, World!\n");
CFRetain(str);
CFRelease(str);
	    
	  

CFStringRef représente une chaîne de caractère au niveau le plus bas des librairies d'Apple, Inc. Cette référence s'alloue en utilisant la méthode CFSTR. Enfin, il faudra utiliser les méthodes CFReatain et CFRelease pour ajuster le compteur de la référence.

Point important : Les objets préfixés de CF représente un objet du CoreFoundation