2009-12-04 16 views
1

Dans un projet objectif de C avec GC a permis, j'allouons un tableau de taille variable sur la pile comme ceci:alloca et ObjectiveC Garbage Collector

MaValue *myStack = alloca((sizeof(id) * someLength)); 

(La raison pour laquelle je veux faire ce n'est pas important :) Ensuite, dans une boucle, je pousse et pop des choses sur/de myStack. Certaines des choses que je pousse sur la pile sont de nouveaux objets qui ne sont référencés nulle part ailleurs. Mon instinct me dit que le garbage collector de l'objectif C ne connaît pas ces pointeurs et collecterait donc les nouveaux objets (autrement non référencés). Une partie de cette croyance vient de la pensée, que l'objectif C GC n'est pas vraiment conservateur mais "connaît ses pointeurs" (par exemple, à travers une carte de pile).

Cependant, dans toutes mes expériences (en insérant des appels [[NSGarbageCollector defaultCollector] collectExhaustively]), je n'ai pas récupéré ces objets - ce qui est bon, mais inattendu. Il semble donc que le GC analyse la pile entière et, par exemple, suppose de manière conservatrice un entier qui a la valeur d'un pointeur valide pour être vraiment un pointeur.

Est-ce correct? Ou est-ce que je manque quelque chose?

+0

Est-ce que MaValue 'un type de classe Objective-C? Si oui, vous devriez déclarer ceci comme' MaValue ** myStack = ... ', c'est-à-dire un pointeur vers un pointeur, puisqu'il s'agit d'un tableau de pointeurs vers des objets. être affecté sur le tas, auquel cas le GC prend le relais pour la gestion de la mémoire Vous ne pouvez pas avoir d'instances d'objets Objective-C sur la pile, seulement des pointeurs vers elles. –

Répondre

3

Il se comporte correctement. Alors que le collecteur analyse le tas exactement [autant que possible] en ce que chaque classe a une disposition et que seuls les emplacements qui se réfèrent à des objets ou utilisent __strong sont analysés, la pile doit être scannée de manière conservatrice. Chaque emplacement de pointeur et pointeur aligné sur le pointeur sur la pile doit être analysé à la recherche de références.

Ainsi, votre alloca() fait tomber le pointeur de la pile et le collecteur les analyse tous. Vous devriez probablement lancer une affirmation pour vous assurer que l'espace alloca'd est aligné sur le pointeur, car le comportement est indéfini.

En fait, vous ne devriez vraiment pas utiliser alloca() du tout. Même la page de manuel indique

La fonction alloca() est la machine et dépend du compilateur; son utilisation est déconseillée.

À la place, utilisez NSAllocateCollectable() pour allouer un segment analysé d'espace de segment. À moins que vous ne parliez de nombreuses allocations par rapport à vos autres opérations, les frais généraux devraient être minimes. En outre, vous ne courez plus le risque de dépasser la taille de pile maximale d'un thread (qui n'est pas grande et change en fonction du thread sur lequel vous travaillez et de la manière dont il est alloué.)