2010-04-15 8 views
2

Ci-dessous, j'ai écrit une liste primitive singulièrement liée en C. La fonction "addEditNode" DOIT recevoir un pointeur par valeur, ce qui, je devine, signifie que nous pouvons éditer les données du pointeur mais ne pouvons pas le pointer ailleurs. Si j'alloue de la mémoire en utilisant malloc dans "addEditNode", quand la fonction retourne, puis-je voir le contenu de first-> next? La deuxième question est la suivante: dois-je libérer d'abord -> suivant ou est-ce seulement le premier que je devrais libérer? Je cours dans des failles de segmentation sous Linux.Question sur le passage d'un pointeur vers une structure en C à une fonction?

#include <stdio.h> 
#include <stdlib.h> 

typedef struct list_node list_node_t; 

struct list_node 
{ 
    int value; 
    list_node_t *next; 
}; 

void addEditNode(list_node_t *node) 
{ 
    node->value = 10; 
    node->next = (list_node_t*) malloc(sizeof(list_node_t)); 
    node->next->value = 1; 
    node->next->next = NULL; 
} 

int main() 
{ 
    list_node_t *first = (list_node_t*) malloc(sizeof(list_node_t)); 

    first->value = 1; 
    first->next = NULL; 

    addEditNode(first); 

    free(first); 

    return 0; 
} 
+0

Est-ce que c'est ce devoir? Il devrait avoir l'étiquette de devoirs si oui. Au-delà, le code ci-dessus est bien sauf pour votre libre. Vous devez libérer toute la mémoire que vous avez mallocée. Créez une boucle qui traverse la liste, libérant les nœuds au fur et à mesure. –

Répondre

0

D'abord, oui, vous pouvez « voir » le contenu de first->next lorsque la fonction retourne. node->next est une valeur dans la structure pointée par node, qui pointe au même endroit que first. Lorsque vous passez le pointeur first par valeur, seul le pointeur lui-même est copié, pas la structure entière vers laquelle il pointe. En d'autres termes, *first dans main est exactement les mêmes données que *node dans addEditNode (pas une copie), il est juste que chaque fonction a un différent pointeur (celui qui est appelé first et un appelé node) qui pointent vers cette seule structure. Deuxièmement, vous devez également libérer node->next ou vous aurez une fuite. Lorsque vous libérez un pointeur sur une structure, ce sont et non des pointeurs récursivement libres qui sont membres de cette structure.

Cependant, je ne vois rien dans ce code qui soit incorrect ou qui devrait provoquer une erreur de segmentation (une fuite ne provoquera pas de segfault).

1

Si j'alloue de la mémoire en utilisant malloc dans "addEditNode", puis-je voir le contenu de first->next?

Oui, vous pouvez le voir dans main.

Deuxième question est-ce que je dois libre premier-> prochaine ou est-ce seulement le premier que je devrais libérer?

Vous devriez également libérer first->next, sinon vous aurez une fuite de mémoire.

Erreur de segmentation que vous pourriez rencontrer si vous essayez de déréférencer first après l'avoir éliminé. Notez toutefois que la suppression d'un noeud de la liste liée nécessite également de réorganiser les pointeurs pour conserver la liste dans un état valide. Vous devriez écrire une fonction séparée pour cela.

2

.. signifie que nous pouvons modifier les données du pointeur, mais ne peut pas pointer vers quelque chose d'autre ...

Oui

Si j'allouent de la mémoire à l'aide malloc "addEditNode", quand la fonction retourne, puis-je voir le contenu de first-> next?

Oui. La mémoire est allouée sur le tas, vous pouvez donc y accéder.Notez que vous êtes toujours responsable de la libération de la mémoire.

Deuxième question est-ce que je dois libre premier-> suivant ou est-ce seulement le premier que je devrais libérer?

Oui. Vous êtes censé libérer toute la mémoire allouée sur le tas.


Bien, il y a une fuite de mémoire (first->next pas free d), mais vous ne devriez probablement pas seg faute.

Note:

node->next = (list_node_t*) malloc(sizeof(list_node_t)); 

casting explicite est pas nécessaire en cas de malloc en C (nécessaire en C++). Ce qui suit est très bien.

node->next = malloc(sizeof(list_node_t)); 
0

Un pointeur est un entier qui désigne une adresse dans la mémoire. Les détails de «mémoire» sont laissés non déclarés ici; sachez simplement qu'un pointeur contient un nombre qui est un octet absolu dans l'espace d'adressage de votre programme. Lorsque vous transmettez un pointeur, vous transmettez une adresse. Ainsi, en modifiant les données à l'adresse, vous faites en sorte que vos modifications soient visibles en dehors de la fonction locale. Alors oui, vous verrez les changements effectués dans addEditNode() dans main(). Lorsque vous allouez dynamiquement de la mémoire, vous devez toujours la libérer. Les modifications apportées au tas sont globales pour le programme.