web-dev-qa-db-fra.com

Est-il correct d'utiliser malloc () / free () "classique" dans les applications Objective-C / iPhone?

Je joue avec le développement d'iPhone depuis un certain temps, et même si cela semble un peu gênant lorsque vous êtes un développeur .NET "noyau dur", ce n'est pas si mal une fois que vous vous y êtes habitué.

Dans chaque livre que j'ai lu sur Objective-C, il n'est question que de conservation/libération (comptage de références) pour la gestion de la mémoire. En tant que développeur C/C++ ancien, il semble étrange que l'allocation de la manière "normale", en utilisant malloc () et free (), ne soit mentionnée que dans certaines notes de bas de page.

Je sais que malloc () et free () fonctionnent dans Objective-C, mais je suis curieux de savoir si c'est une pratique courante ou non. Après tout, si je veux allouer un tableau de 100 entiers, il semble que ce soit le moyen le plus efficace de le faire:

int *array = malloc(sizeof(int) * 100);

memset(array,0,sizeof(int) * 100);

// use the array

free(array);

Est-ce vraiment le meilleur moyen, ou devrais-je éviter la gestion de la mémoire C ordinaire?

53
Philippe Leybaert

Il y a un wrapper Objective-C autour de la mémoire brute que j'aime beaucoup utiliser pour des tâches similaires: NSMutableData. Il a l'avantage de vous permettre de conserver/libérer la propriété et de développer facilement la baie (sans que vous ayez à effectuer vous-même la réaffectation).

Votre code ressemblerait à:

NSMutableData* data = [NSMutableData dataWithLength:sizeof(int) * 100];
int* array = [data mutableBytes];
// memory is already zeroed

// use the array

// decide later that we need more space:
[data setLength:sizeof(int) * 200];
array = [data mutableBytes]; // re-fetch pointer in case memory needed to be copied

// no need to free
// (it's done when the autoreleased object is deallocated)
79
Nikolai Ruhe

C'est très bien - Objective-C est un sur-ensemble strict de C, donc si vous voulez écrire du C simple, rien ne vous empêche de le faire. Dans de nombreux cas, il est avantageux d'utiliser malloc et free pour éviter la surcharge du runtime Objective-C.

Par exemple, si vous devez allouer dynamiquement un tableau d'un nombre inconnu d'entiers, c'est souvent plus simple et plus facile:

int *array = malloc(N * sizeof(int));  // check for NULL return value!
// use array[0]..array[N-1]
...
free(array);

Contre:

NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:N];
// use NSMutableArray methods to do stuff with array; must use NSNumbers instead
// of plain ints, which adds more overhead
...
[array release];

Je travaillais sur un jeu de mots pour iPhone et nous avons dû charger un dictionnaire de plusieurs mégaoctets de mots valides. La liste de mots a été chargée dans un tableau géant char alloué avec malloc(), avec quelques optimisations intelligentes pour réduire encore plus la taille de la mémoire. Évidemment pour quelque chose comme ça, la surcharge d'utilisation d'un NSArray est complètement impraticable sur l'iPhone limité. Je ne sais pas exactement ce qu'est la surcharge, mais c'est certainement plus d'un octet par caractère.

48
Adam Rosenfield

Bien sûr, vous pouvez utiliser ces fonctions, car Objective-C est simplement un surensemble de C. Cependant, il est assez rare de faire ce genre de chose, car Objective-C contient des objets et des façons de faire c'est plus facile.

Après tout, vous pouvez écrire le code ci-dessus comme suit:

NSMutableArray *array = [[NSMutableArray alloc] init];

//Use the array, adding objects when need be

[array release];

Bien que vous deviez créer des objets NSNumber pour stocker les ints (puisque NSArray ne permet pas l'ajout de types non-objets), il est généralement plus courant d'utiliser , car il est plus facile de déplacer des données, et les classes de tableaux sont intégrées plus fréquemment avec d'autres classes Cocoa, et la gestion de la mémoire est généralement plus simple que la gestion de la mémoire C standard.

De plus, si vous commencez à ajouter ou à supprimer des objets du tableau, les objets du tableau Cocoa facilitent cela.

5
Alex Rozanski

Si vous avez affaire à des types C standard, ce n'est pas moins commun ou "OK" qu'en C. C'est comme cela que cela se fait en C, qui fait partie d'Objective-C.

Il n'est pas non plus inhabituel d'écrire une sorte d'encapsuleur d'objets autour de ces choses pour le mettre en harmonie avec le reste de Cocoa (KVO, gestion de la mémoire, etc.). Vous pouvez donc créer une classe IntArray qui effectue la mallocing en arrière-plan afin que vous puissiez la conserver et la libérer au besoin. Notez que ce n'est pas strictement nécessaire - cela peut être pratique si ce type de structure est une partie importante de votre programme.

3
Chuck

Il est parfaitement possible d'utiliser malloc et libre de faire votre propre gestion de la mémoire. En fait, allocWithZone: De NSObject utilise malloc pour obtenir la mémoire.

2
Nikolai Ruhe