C warning Sentinelle manquante dans l’appel de fonction

Ceci est mon avertissement.

Missing sentinel in function call 

Comment je peux l’enlever

J’utilise le compilateur linux & gcc.

Il semble que vous n’ayez pas terminé une déclaration de tableau avec NULL . Sans la valeur null, vous pourriez avoir des problèmes de mémoire car le moteur d’exécution ne saura pas où le tableau se termine et le prochain bit de mémoire démarre.

Je viens de tomber sur le même problème. Le code qui le causait pour moi était …

 execl("/bin/bash", "/bin/bash", fname, '\0'); 

mais ça devrait être …

 execl("/bin/bash", "/bin/bash", fname, (char *)0); 

Le problème avec la première version est que la liste des parameters se termine par un pointeur nul. Mais ‘\ 0’ n’est pas un pointeur nul, c’est un caractère nul. Donc la valeur (0) est correcte, c’est juste que le type est faux.

Le (char *) 0 est également zéro, mais converti en un pointeur de caractère , qui est un pointeur nul (c’est-à-dire qu’il pointe vers l’adresse 0). Cela est nécessaire pour que le système puisse déterminer où la liste de parameters se termine, de sorte qu’elle ne continue pas à rechercher les parameters après le dernier. Faire cela donnerait des pointeurs invalides qui pourraient pointer vers n’importe quelle mémoire – ce qui provoquerait probablement une erreur de segmentation.

Ce (char *) 0 s’appelle la sentinelle et c’est ce qui manquait dans le premier exemple.

Notez enfin que NULL est défini comme (void *) 0, donc

 execl("/bin/bash", "/bin/bash", fname, NULL); 

Fonctionne aussi bien et est un peu plus pratique. (Merci à @mah pour ça).

Dans Xcode, si vous codez dans objective-c et que vous utilisez des méthodes qui prennent une liste de parameters variables, vous devez append un object nul à la fin de la liste.

Par exemple:

N SArray * names = [NSArray arrayWithObjects: @ “Nom1”, @ “Nom2”]; // entraînera l’avertissement mentionné ci-dessus

Toutefois, NSArray * names = [NSArray arrayWithObjects: @ “Name1”, @ “Name2”, nil]; //Correct

J’espère que cela aidera!

Utilisez (void*)0 ou (void *)NULL au lieu de NULL comme sentinelle.

L’avertissement est généré par l’atsortingbut de fonction sentinel mentionné par Jichao . Documenté à: https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Function-Atsortingbutes.html#index-g_t_0040code_007bsentinel_007d-function-atsortingbute-3226 qui indique:

Une valeur NULL valide dans ce contexte est définie sur zéro avec tout type de pointeur. Si votre système définit la macro NULL avec un type entier, vous devez append une dissortingbution explicite. GCC remplace stddef.h par une copie qui redéfinit NULL de manière appropriée.

Dans ANSI C, NULL peut être 0 ou (void *)0 , et seul le pointeur satisfait cet atsortingbut, voir aussi: Quelle est la différence entre NULL, ‘\ 0’ et 0

Alors que 0 serait converti en pointeur nul avec un argument de pointeur régulier, il est impossible de différencier le nombre entier zéro du pointeur zéro avec vararg, de sorte que la différence est cruciale. Voir: argument par défaut promotion du pointeur

Il est vrai que GCC garantit que NULL est le pointeur et que NULL est fourni par GCC dans stddef.h (certains en-têtes C ANSI sont dans GCC, d’autres dans la glibc), je ne suis pas certain que sentinel soit un GCC extension pour commencer.

Mais j’écrirais toujours (void *)NULL ou (void*)0 pour être sûr.

De plus, POSIX et man execl requièrent “un pointeur nul” pour la fin de la fonction execl (), qui est un exemple prototype de l’utilisation de sentinelle.

NULL n’est pas garanti pour fonctionner ici car il s’agit d’une “constante de pointeur nul”, qui n’est pas nécessairement un “pointeur nul”, donc en utilisant (void *)0 partout où vous êtes plus compatible avec les API bien connues. Voir aussi: ((void *) 0) est-il un pointeur nul constant? || Est-ce que (int *) 0 est un pointeur nul?

GCC 5.2.0 fournit execl tant que intégré et positionne la sentinel programme:

 DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECL, "execl", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_SENTINEL_NOTHROW_LIST) 

Il existe également une version glibc 2.21 de execl qui n’a pas d’atsortingbut.

Un exemple sortingvial:

 #include  #include  void print_ssortingngs(const char* first, ...) __atsortingbute__((sentinel)); void print_ssortingngs(const char* first, ...) { va_list ap; const char* tmp; if (!first) return ; printf("%s\n", first); va_start(ap, first); while (1) { tmp = va_arg(ap, const char*); if (tmp == 0) break; printf("%s\n", tmp); }; va_end(ap); } int main() { print_ssortingngs("how are you?", "i'm fine", "and you?", NULL); return 0; } 

En gros, si vous appelez print_ssortingngs en tant que print_ssortingngs("how are you?", "I'm fine", "and you?") Qui n’a pas de fin NULL , GCC se plaindra “sentinelle manquante”.

Parce que nous ajoutons l’atsortingbut de fonction sentinelle à la fonction print_ssortingngs . C’est une extension gcc pour spécifier que les arguments de la variable doivent se terminer par NULL. Donc, si vous ne terminez pas les arguments variables avec NULL, le compilateur pourrait le détecter et afficher l’avertissement.

Sentinel signifie protéger ou protéger. Donc, dans ce contexte, l’erreur se produit car vous risquez de manquer les parameters de protection. Si vous utilisez un tableau ou un dictionnaire, assurez-vous qu’après le nommage des objects, vous les finissez avec le mot-clé nil.

Exemple:

 [NSDictionary dictionaryWithObjectsAndKeys:@"UIAlertView", kSectionTitleKey, @"Show Custom", kLabelKey, @"AlertsViewController.m - alertOtherAction", kSourceKey]; 

L’instruction ci-dessus produira une erreur “Sentinelle manquante dans l’appel de fonction”

Syntaxe correcte:

 [NSDictionary dictionaryWithObjectsAndKeys:@"UIAlertView", kSectionTitleKey, @"Show Custom", kLabelKey, @"AlertsViewController.m - alertOtherAction",kSourceKey,nil]; 

Vous pouvez passer NULL comme: execl (“/ bin / bash”, “ls”, “- l”, NULL); Le dernier paramètre doit toujours être 0. C’est un terminateur NULL . Comme la liste des arguments est variable, nous devons avoir un moyen de dire à C quand il doit se terminer.

J’ai finalement trouvé un moyen de se débarrasser de cet avertissement étrange et ennuyeux.

Tout ce que vous devez faire est de convertir un pointeur nul en un type de pointeur approprié.

Dans le cas de UIAlertView cela se passe comme suit:

 UIAlertView* alert = [ [ UIAlertView alloc ] initWithTitle: @"Title" message: @"Message" delegate: nil cancelButtonTitle: @"Cancel" otherButtonTitles: @"OK", ( NSSsortingng* )nil ]; 

Notez la dissortingbution ( NSSsortingng* )nil .

Essayez-le et dites-moi si cela fonctionne pour vous.