Essentiellement, j'ai une structure pour une liste chaînée dans mon code,
struct node{
char* val;
struct node *next;
};
Puis, plus tard, j'essaye d'y faire des choses ...
...
addr = malloc(sizeof(struct node));
addr->val = malloc(72);
addr->val = "";
snprintf(addr->val, 1000, "%s", ident);
...
... Cela me donne un défaut de segmentation au niveau du snprintf. Valgrind dit le texte suivant
Process terminating with default action of signal 11 (SIGSEGV)
==10724== Bad permissions for mapped region at address 0x40566B
==10724== at 0x4EB0A32: vsnprintf (vsnprintf.c:112)
==10724== by 0x4E8F931: snprintf (snprintf.c:33)
==10724== by 0x4016CC: id (Analyzer.c:267)
...
Je suis assez nouveau en C par opposition à C ++, mais je pensais qu'appeler malloc sur le char * devrait le rendre valide, d'autant plus que je peux l'initialiser et l'imprimer, donc je ne comprends pas pourquoi le snprintf ne fonctionnerait pas. J'ai aussi demandé à mon programme d'imprimer les adresses des deux variables, et l'adresse dont se plaint valgrind est en effet de addr-> val.
J'ai également essayé d'utiliser strcpy au lieu de snprintf mais j'ai eu le même résultat.
Merci.
3 réponses
addr->val = malloc(72);
Cette ligne alloue dynamiquement 72 octets et attribue l'adresse de cette région mémoire à addr->val
.
addr->val = "";
Cela définit ensuite addr->val
pour qu'il pointe vers l'adresse d'une constante de chaîne, en supprimant l'adresse de la zone de mémoire malléable qu'elle contenait auparavant, provoquant une fuite de mémoire.
Lorsque vous essayez ensuite d'utiliser snprintf
, vous essayez d'écrire dans une chaîne littérale. Comme ceux-ci sont généralement stockés dans une section de mémoire en lecture seule, toute tentative de le faire entraîne un vidage de mémoire.
Il n'y a pas besoin de addr->val = "";
. Il jette la mémoire allouée; il ne définit pas cette mémoire allouée sur une chaîne vide, ce que vous pensiez probablement faire. Même si c'est le cas, c'est de toute façon inutile car snprintf
écrasera tout ce qui pourrait s'y trouver.
addr->val = malloc(72);
addr->val = "";
La deuxième ligne réassigne addr->val
à une adresse dans la section en lecture seule (où se trouvent les littéraux de chaîne), et rejette l'adresse d'allocation de malloc
, ce qui peut conduire à une fuite de mémoire potentielle.
Je sais que tu veux l'effacer. Pour attribuer des chaînes, vous devez utiliser strcpy()
strcpy(addr->val, "");
Mais puisque vous souhaitez le vider, il est plus simple de mettre le premier caractère à zéro:
addr->val[0] = '\0';
De plus, vous essayez de faire un travail potentiellement dangereux:
snprintf(addr->val, 1000, "%s", ident);
Vous aviez l'intention d'allouer 72 octets, mais pourquoi nous le deuxième paramètre allant jusqu'à 1k? Changez-le en un numéro plus sûr:
snprintf(addr->val, 72, "%s", ident);
Tout devrait aller bien d'ici là.
Le code
addr->val = malloc(72);
addr->val = ""; <====
Remplace le pointeur val
par "", adresse d'une zone statique, composée de 1 caractère (de valeur 0). Supprimez cette ligne.
Et
snprintf(addr->val, 1000, "%s", ident);
Acceptez une longueur de 1000 alors que vous n'avez alloué que 72 caractères.
snprintf(addr->val, 72, "%s", ident);
Est mieux.
De nouvelles questions
c
C est un langage de programmation à usage général utilisé pour la programmation système (OS et embarqué), les bibliothèques, les jeux et les plateformes multiples. Cette balise doit être utilisée avec des questions générales concernant le langage C, tel que défini dans la norme ISO 9899 (la dernière version, 9899: 2018, sauf indication contraire - également balise les demandes spécifiques à la version avec c89, c99, c11, etc.). C est distinct de C ++ et il ne doit pas être combiné avec la balise C ++ en l'absence d'une raison rationnelle.