39 votes

Argv [n] est-il accessible en écriture?

C11 5.1.2.2.1/2 dit:

Les paramètres argc et argv et les chaînes pointées par l' argv tableau est être modifiable par le programme, et de conserver leur dernier-valeurs stockées entre programme de démarrage et de fin de programme.

Mon interprétation est qu'il indique:

int main(int argc, char **argv)
{
    if ( argv[0][0] )
        argv[0][0] = 'x';   // OK

    char *q;
    argv = &q;              // OK
}

cependant, il ne dit rien à ce sujet:

int main(int argc, char **argv)
{
    char buf[20];
    argv[0] = buf;
}

Est - argv[0] = buf; - il permis?

Je peux voir (au moins) deux arguments:

  • La citation ci-dessus délibérément mentionné argv et argv[x][y] mais pas argv[x], de sorte que l'intention était qu'il n'est pas modifiable
  • argv est un pointeur non-const objets, donc en l'absence d'un texte spécifique à l'effet contraire, nous devons supposer qu'ils sont modifiables objets.

9voto

chux Points 13185

OMI, code comme celui - argv[1] = "123"; UB.


"Les paramètres argc et argv et les chaînes pointées par le tableau argv est être modifiable par le programme, et de conserver leur dernier-valeurs stockées entre programme de démarrage et de fin de programme." C11dr §5.1.2.2.1 2

Rappelons qu' const est entré en C, de nombreuses années après C est la création.

Un peu comme char *s = "abc"; est valide alors qu'il devrait être const char *s = "abc";. La nécessité d' const n'a pas été requise d'autre trop de code existant aurait rompu avec l'introduction de l' const.

De la même manière, même si argv aujourd'hui, devrait être considérée char * const argv[] ou une autre signature avec const, le manque d' const dans la char *argv[] ne se termine pas spécifier l' const-ness besoins de l' argv, argv[]ou argv[][]. L' const-ness besoins doivent être pilotées par la spécification.

De ma lecture, depuis la spécification est muet sur la question, c'est UB.

Un comportement indéfini est d'indication contraire dans la présente Norme Internationale par les mots ‘un comportement indéfini" ou par l' omission d'une définition explicite de comportement" §4 2


[edit]:

main() est une très particulière de la fonction de C. Ce qui est autorisé dans d'autres fonctions peuvent ou peuvent ne pas être autorisés en main(). Le C spec détails attributs sur ses paramètres que, compte tenu de la signature int argc, char *argv[] qui ne le sont pas ont besoin. main(), contrairement à d'autres fonctions en C, peut avoir une autre signature int main(void) et potentiellement d'autres. main() n'est pas réentrant. Comme le C spec sort de sa façon de détailler ce qui peut être modifié: argc, argv, argv[][], il est raisonnable de se demander si argv[] est modifiable en raison de son omission de la spec affirmant que le code.

Compte tenu de la spécialité de l' main() , et que l'omission de le spécifier argv[] modifiables, un conservateur programmeur devrait traiter cette grisaille comme UB, dans l'attente de C spec clarification.


Si argv[i] est modifiable sur une plate-forme donnée, certainement la gamme de i ne doit pas dépasser argc-1.

En tant que "argv[argc] doit être un pointeur null", assignining argv[argc] d'autre chose que de l' NULL semble être une violation.

Bien que les cordes sont modifiables, le code ne doit pas dépasser l'original de la longueur de la chaîne.

char *newstr = "abc";
if (strlen(newstr) <= strlen(argv[1])) 
  strcpy(argv[1], newstr);

0voto

Serge Ballesta Points 12850

argc est juste un int et est modifiable sans aucune restriction.

argv est un char ** modifiable. Cela signifie que argv[i] = x est valide. Mais cela ne dit rien sur argv[i] étant lui-même modifiable. Donc argv[i][j] = c conduit à un comportement indéfini.

La fonction getopt de la bibliothèque standard C modifie argc et argv mais ne modifie jamais les tableaux de caractères réels.

-1voto

david.pfx Points 5594

La réponse est que argv est un tableau et oui, son contenu est modifiable.

La clé est plus haut dans la même rubrique:

Si la valeur de argc est supérieure à zéro, le tableau des membres de argv[0] par argv[argc-1] inclusive doit contenir des pointeurs vers des chaînes, qui sont donnés mise en œuvre-les valeurs définies par l'hôte de l'environnement avant le démarrage du programme.

De ce fait, il est clair que argv est d'être considéré comme un tableau d'une longueur spécifique (argc). Puis *argv est un pointeur vers ce tableau, après avoir pourri un pointeur.

Lire dans ce contexte, la déclaration à l'effet que "argv est modifiable...et de conserver son contenu' entend clairement que le contenu de ce tableau modifiable.

Je concède qu'il reste une certaine ambiguïté dans le libellé, en particulier quant à ce qui pourrait arriver si argc est modifié.


Juste pour être clair, ce que je veux dire c'est que j'ai lu cette langue en ce sens:

[le contenu de l'] argv [array] et les chaînes pointées par le tableau argv est modifiable...

Donc, les pointeurs dans le tableau et les chaînes qui leur point de sont en lecture-écriture de la mémoire, aucun mal n'est fait par les changer, et à la fois de préserver leurs valeurs pour la vie du programme. Je m'attends à ce que ce comportement se retrouve dans tous les grands C/C++ runtime library implémentations, sans exception. Ce n'est pas AC.

L'ambiguïté est la mention de argc. Il est difficile d'imaginer n'importe quel but ou la mise en œuvre dans laquelle la valeur de argc (ce qui semble être simplement un local paramètre de la fonction) ne peut pas être changé, alors pourquoi le mentionner? La norme stipule clairement qu'une fonction puisse modifier la valeur de ses paramètres, alors pourquoi traiter argc spécialement à cet égard? C'est cette inattendue mention de argc, qui a déclenché cette préoccupation concernant les argv, qui seraient autrement passer sans commentaire. Supprimer argc de la phrase et de l'ambiguïté disparaît.

-2voto

haccks Points 33022

Il est clairement mentionné que argv et argv[x][x] sont modifiables. Si argv est modifiable, il peut pointer vers un autre premier élément d'un tableau de char et donc argv[x] peut pointer vers le premier élément d'une autre chaîne. En fin de compte, argv[x] est également modifiable et cela pourrait être la raison pour laquelle il n'est pas nécessaire de le mentionner explicitement dans la norme.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X