clang
n'effectue aucune analyse inter-procédures, du moins pas encore. Même si c'était le cas, il ne pourrait pas nécessairement attraper cette "erreur" - les permutations de chemins de code potentiels ont tendance à augmenter de façon exponentielle, ce qui en fait une impossibilité pratique.
clang
fonctionne avec un ensemble d'heuristiques qui fonctionnent «la plupart du temps». Heureusement, les règles de gestion de la mémoire Cocoa ont tendance à être assez uniformes, de sorte que les heuristiques fonctionnent pour la plupart des utilisations. L'exemple que vous avez donné n'est pas vraiment couvert par les règles de gestion de la mémoire, mais je pense que la plupart des gens (dont moi-même) ont tendance à classer votre exemple comme "Vous avez documenté par l'API que l'appelant est leaker()
responsable de release
l'objet retourné ". Ceci est essentiellement analogue aux méthodes de style - (NSString *)init...
.
clang
clang
sait que les méthodes commençant par init...
renvoient un objet 'inédit' et qu'il appartient aux appelants de s'assurer qu'il est correctement libéré. Cela fait partie du noyau de l'heuristique - il n'a pas besoin d'un programme entier ou d'une analyse inter-procédurale pour effectuer la vérification du compte de référence - si un bloc de code local obtient un objet via une méthode init...
, ce bloc de code local doit s'assurer qu'il est correctement released
. Naturellement, si le bloc de code local, et l'objet en question, fait partie d'une méthode init...
elle-même, elle est couverte par la même "règle", donc elle reçoit une exception.
Qu'est-ce que vous voulez sans doute est quelque chose comme:
NSString* leaker() __attribute__((ns_returns_retained))
{
return [[NSString alloc] init];
}
Cela permet à l'analyseur savoir que leaker()
retourne un objet « retenu », que l'appelant est responsable de la libération correctement, il. Bien que je ne l'ai pas testé, je soupçonne fortement que le serait détecté « fuite » au point où leaker()
est appelé, à savoir:
void test(void)
{
NSString *leaked = leaker();
// Previous line should be caught as a "leak" by clang.
}
Ceci est l'une des limites malheureuses de tout analyseur statique, pas seulement clang
.