0

Il ne se soucie pas de cela:Est-ce que la portée de ce que "Construire et Analyser" de Xcode va attraper comme une fuite supposée être aussi limitée?

NSString* leaker() 
{ 
return [[NSString alloc] init]; 
} 

Je pensais que cela aurait été assez intelligent pour vérifier si les chemins de code pourrait appeler cette fonction sans relâcher sa valeur de retour (je ne voudrais pas le code normalement de cette façon, Je ne fais que tester l'analyseur).

Il rend compte cela comme une fuite:

NSString* leaker() 
{ 
NSString* s = [[NSString alloc] init]; 
[s retain]; 
return s; 
} 

mais pas ceci:

NSString* leaker() 
{ 
NSString* s = [[NSString alloc] init]; 
// [s retain]; 
return s; 
} 

qui me semble particulièrement faible pour. Est-ce qu'il analyse seulement dans le cadre local? Si l'outil ne peut pas comprendre ce genre de choses, comment puis-je m'attendre à ce qu'il réponde aux erreurs que je pourrais commettre?

Répondre

4

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....

clangclang 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.

Questions connexes