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.

-1
Vincent Wells 26 nov. 2017 à 05:14

3 réponses

Meilleure réponse
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.

2
Ry- 26 nov. 2017 à 04:38
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à.

0
iBug 26 nov. 2017 à 02:23

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.

0
e2-e4 26 nov. 2017 à 02:19
47492396