web-dev-qa-db-fra.com

Vérifier la taille d'un objet en Objective-C

J'essaye de trouver la taille d'un objet objective-c. J'utilise quelque chose de similaire à:

    NSLog(@"sizeof myObject: %ld", sizeof(*myObject));

Cela me donne juste la taille du pointeur.

Qu'est-ce que je fais mal?

35
Coocoo4Cocoa

Tout ce que le compilateur sait, c'est le pointeur, c'est pourquoi vous récupérez la taille du pointeur. Pour voir la taille de l'objet alloué, utilisez l'un des extraits de code suivants:

Avec ARC:

#import <malloc/malloc.h>

// ...

NSLog(@"Size of %@: %zd", NSStringFromClass([myObject class]), malloc_size((__bridge const void *) myObject));

Sans ARC:

#import <malloc/malloc.h>

// ...

NSLog(@"size of myObject: %zd", malloc_size(myObject));

Mike Ash a un article décent sur certains des composants internes de l'exécution d'Obj-C sur son blog de questions-réponses: http://mikeash.com/?page=pyblog/friday-qa-2009-03-13-intro -à-l'objectif-c-runtime.html

53
Jason Coco

Dans le GNU runtime Objective-C, vous pouvez utiliser (vous devez importer <objc/objc-api.h>:

class_get_instance_size ([MyClass class]);

Sur Mac OS X, vous pouvez utiliser (vous devrez peut-être importer <objc/runtime.h>):

class_getInstanceSize ([MyClass class]);

Ces fonctions renverront la quantité de mémoire nécessaire pour allouer un objet, elles n'incluront pas la mémoire allouée par un objet lors de son initialisation.

19
dreamlax

Tout d'abord, je pense qu'il est clair d'après les articles ci-dessus que la taille object est donnée par malloc_size (myObject), comme suggéré par Jason et également dans le manuel de référence de Mac OS:

"La fonction malloc_size ( ptr) renvoie la taille du bloc de mémoire qui soutient l'allocation pointée par ptr. La taille du bloc de mémoire est toujours au moins égale aussi grande que l’allocation qu’il recule et peut être plus importante. ( http://developer.Apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/malloc_size.3.html )

Mais si vous souhaitez connaître la taille du dictionnaire, gardez à l'esprit le point suivant:

Le dictionnaire stocke les paires clé-valeur et ne contient pas l'objet lui-même dans la partie valeur, mais augmente simplement le nombre de rétention de l'objet qui devait être " ajouté "et garde une référence de cet objet avec lui-même. Maintenant, le dictionnaire lui-même ne contient que les références aux différents objets (avec une clé attachée). Donc si, par hasard, vous recherchez la taille de l'objet de tous les objets référencés par le dictionnaire, techniquement, ce ne serait pas la taille du dictionnaire. La taille du dictionnaire serait la somme de la taille de toutes les clés plus la taille de toutes les références de valeur par rapport aux clés plus la taille du NSObject parent. Si vous souhaitez toujours connaître la taille des objets référencés, essayez d'itérer sur le tableau des valeurs du dictionnaire:

NSArray *myArray = [myDictionary allValues];
id obj = nil;
int totalSize = 0;
for(obj in myArray)
{
    totalSize += malloc_size(obj);
}
//totalSize now contains the total object size of the refered objects in the dictionary.

J'espère que cela répond à la question.

14
Ameer Sheikh

La taille d'un objet (objectif-c) n'est pas facile à trouver car elle n'est même pas facile à définir. Qu'entendez-vous par "taille d'un objet objectif-c"?

La taille de la référence est la taille d'un pointeur (comme renvoyé par sizeof (obj_ref)).

La taille de la mémoire qui a été allouée lors de la création (+ alloc) peut être trouvée par la façon dont Jason a donné dans la première réponse. Mais cela dépend du runtime. Le runtime gnu diffère du runtime Apple. Finalement, il ne s'agit que de la mémoire dont ont besoin les types de données primitifs dont l'instance se compose. Mais not la mémoire qui pourra être allouée plus tard (c'est-à-dire lors de l'initialisation (-init)) pour les objets référencés par les ivars ou les chaînes.

Une instance de la classe

@interface FirstClass
{
    int _someInt;
    char _someChar;
}
…
@end

nécessite au moins 5 octets (sur de nombreux systèmes - la taille de int peut varier) plus une surcharge statique si le runtime en a besoin. La taille d'un tel objet est évidente.

Mais pour une instance de la classe

@interface SecondClass
{
    FirstClass *_someObject;
    char *_name;
    id _data;
}
…
@end

la définition de la "taille" est compliquée. L'objet a besoin de 12 octets (sur les systèmes 32 bits) plus la surcharge lors de l'allocation. Mais peut-être que le nom fait partie de l'objet et est alloué/libéré par celui-ci. La mémoire dont le nom réel a besoin doit-elle faire partie de la taille de l'objet? Et qu'en est-il des objets référencés?

7
Tilo Prütz

Je suggérerais d'utiliser class_getInstanceSize et malloc_good_size pour voir à quoi cela va s'arrondir. Cela ne montrera pas les ivars et autres choses à l'intérieur de la taille retournée.

#import <malloc/malloc.h>
#import <objc/runtime.h>

NSLog(@"Object Size: %zd", malloc_good_size(class_getInstanceSize([yourObject class])));
5
EvilPenguin