C avertissement absence de Sentinelle dans l'appel de fonction

C'est mon avertissement.

Missing sentinel in function call

comment je peux l'enlever.

j'utilise le compilateur linux & gcc.

40
demandé sur ambika 2010-03-09 11:40:52

8 réponses

il semble que vous n'ayez pas terminé une déclaration de tableau avec NULL . Sans le null, vous pouvez avoir une certaine bizarrerie de mémoire car le runtime ne saura pas où le tableau se termine et le prochain morceau de mémoire commence.

62
répondu Michael Gaylord 2014-07-26 11:44:41

je viens de rencontrer le même problème. Le code qui me l'a causé était...

execl("/bin/bash", "/bin/bash", fname, '"151900920"');

mais ça devrait l'être...

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

le problème avec la première version est que la liste des paramètres est censée se terminer avec un pointeur nul. Mais '\0' n'est pas un pointeur null, c'est un caractère nul. Donc la valeur (0) est correcte, c'est juste que le type est erroné.

le (char *) 0 est aussi zéro, mais moulé comme un char pointeur , 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 dire où se termine la liste de paramètres pour qu'il ne continue pas à rechercher les paramètres après le dernier. Faire cela lui obtiendrait des pointeurs invalides qui pourraient pointer vers n'importe quelle mémoire - qui causerait probablement un défaut de segmentation.

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

enfin notez que la valeur NULL est définie comme (void *)0, donc

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

fonctionne aussi bien, et est un peu plus pratique. (Merci à @mah pour cela).

43
répondu Peter Bagnall 2012-09-06 15:23:57

dans Xcode si vous codez dans objective-c et que vous utilisez certaines méthodes qui prennent la liste des paramètres variables, vous devez ajouter nil objet à la fin de la liste.

par exemple:

N SArray *nom = [NSArray arrayWithObjects: @"Nom1", @"Nom2"]; //va entraîner l'avertissement mentionné ci-dessus

cependant, NSArray *names = [NSArray arrayWithObjects: @"Nom1", @"Nom2", nil]; //Correct

Espère que cela va vous aider!

18
répondu kslcam 2010-09-20 10:36:29

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

l'avertissement est généré par l'attribut de fonction sentinel mentionné par Jichao . Documenté à: https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Function-Attributes.html#index-g_t_0040code_007bsentinel_007d-function-attribute-3226 qui dit:

Un NULL valide dans ce contexte est défini comme zéro avec n'importe quel type de pointeur. Si votre système définit la macro NULL avec un type entier, alors vous devez ajouter un cast explicite. Le GCC remplace le stddef.h avec une copie qui redéfinit correctement NULL.

dans ANSI C, NULL peut être soit 0 ou (void *)0 , et seul le pointeur satisfait cet attribut, voir aussi: Quelle est la différence entre NULL, '\0' et 0

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

vrai, GCC garantit NULL pour être le pointeur, et puisque NULL est fourni par GCC dans stddef.h (certains en-têtes ANSI C sont dans GCC, d'autres dans glibc), Je ne suis pas sûr que cela pourrait être cassé depuis sentinel est une extension GCC pour commencer.

mais j'écrirais quand même (void *)NULL ou (void*)0 juste pour être sûr.

de plus, POSIX et man execl requièrent" un pointeur nul "pour la fonction execl () terminaison qui est un exemple prototypique d'usage sentinelle.

NULL n'est pas garanti d'y travailler parce qu'il s'agit d'une "constante de pointeur nulle", qui n'est pas nécessairement "un pointeur null", donc en utilisant (void *)0 partout vous êtes plus cohérent avec les API bien connues. Voir aussi: est ((nul*)0) une constante de pointeur nulle? || Est (int *)0 un pointeur null?

GCC 5.2.0 fournit execl comme un intégré et les ensembles sentinel programmatically on it:

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

il y a aussi une version glibc 2.21 de execl qui n'a pas l'attribut.

7

un exemple insignifiant:

#include <stdio.h>
#include <stdarg.h>

void print_strings(const char* first, ...) __attribute__((sentinel));

void print_strings(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_strings("how are you?", "i'm fine", "and you?", NULL);
    return 0;
}

dans la main, si vous appelez print_strings comme print_strings("how are you?", "I'm fine", "and you?") qui n'a pas de fin NULL , GCC se plaindra"sentinel manquant".

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

2
répondu Jichao 2014-01-12 16:07:20

Sentinelle signifie Garder ou protéger.. Donc dans ce contexte l'erreur se produit parce que vous pourriez manquer les paramètres de garde. Dans le cas où vous utilisez un tableau ou un dictionnaire alors assurez-vous qu'après le nom les objets vous les terminez avec le mot-clé nil.

exemple:

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

la déclaration ci-dessus produira une erreur "appel sentinelle manquant dans la fonction "

syntaxe correcte:

[NSDictionary dictionaryWithObjectsAndKeys:@"UIAlertView", kSectionTitleKey,
              @"Show Custom", kLabelKey,
              @"AlertsViewController.m - alertOtherAction",kSourceKey,nil];
1
répondu taus-iDeveloper 2012-11-20 11:42:21

vous pouvez passer NULL: execl ("/bin / bash","ls","-l", NULL); Le dernier paramètre doit toujours être 0. C'est un Terminator NULL . Puisque la liste d'arguments est variable, nous devons avoir un moyen de dire à C quand il doit se terminer.

1
répondu Sanidhya Srivastava 2014-12-29 15:50:54

j'ai enfin trouvé un moyen de me débarrasser de cet étrange et ennuyeux avertissement.

Tout ce que vous devez faire est de lancer un pointeur nul à un type de pointeur approprié.

dans le cas de UIAlertView il va comme ceci:

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

notez la distribution ( NSString* )nil .

essayez et faites-moi savoir si cela fonctionne pour vous.

-1
répondu medoteddy 2012-09-24 08:55:37