2010-04-29 18 views
2

J'ai simplifié un problème que j'ai essayé d'isoler le problème, mais cela n'aide pas. J'ai un tableau char 2 dimensions pour représenter la mémoire. Je veux transmettre une référence à cette simulation de mémoire à une fonction. Dans la fonction de tester le contenu de la mémoire, je veux juste parcourir la mémoire et imprimer le contenu de chaque ligne.c - problème de déréférencement

Le programme imprime la première ligne et ensuite je reçois un défaut de segmentation.

Mon programme est le suivant:

#include <stdio.h> 

#include <stdlib.h> 

#include <ctype.h> 

#include <string.h> 

void test_memory(char*** memory_ref) { 

    int i; 
    for(i = 0; i < 3; i++) { 
     printf("%s\n", *memory_ref[i]); 
    } 
} 

int main() { 
    char** memory; 
    int i; 
    memory = calloc(sizeof(char*), 20); 
    for(i = 0; i < 20; i++) { 
     memory[i] = calloc(sizeof(char), 33); 
    } 

    memory[0] = "Mem 0"; 
    memory[1] = "Mem 1"; 
    memory[2] = "Mem 2"; 

    printf("memory[1] = %s\n", memory[1]); 

    test_memory(&memory); 

    return 0; 
} 

Cela me donne la sortie:

memory[1] = Mem 1 
Mem 0 
Segmentation fault 

Si je change le programme et créer une version locale de la mémoire dans la fonction par déréférencement du memory_ref , je reçois la sortie droite:

alors:

#include <stdio.h> 

#include <stdlib.h> 

#include <ctype.h> 

#include <string.h> 

void test_memory(char*** memory_ref) { 

    char** memory = *memory_ref; 
    int i; 
    for(i = 0; i < 3; i++) { 
     printf("%s\n", memory[i]); 
    } 
} 

int main() { 
    char** memory; 
    int i; 
    memory = calloc(sizeof(char*), 20); 
    for(i = 0; i < 20; i++) { 
     memory[i] = calloc(sizeof(char), 33); 
    } 

    memory[0] = "Mem 0"; 
    memory[1] = "Mem 1"; 
    memory[2] = "Mem 2"; 

    printf("memory[1] = %s\n", memory[1]); 

    test_memory(&memory); 

    return 0; 
} 

me donne le résultat suivant:

memory[1] = Mem 1 
Mem 0 
Mem 1 
Mem 2 

qui est ce que je veux, mais faire une version locale de la mémoire est inutile parce que je dois être en mesure de modifier les valeurs de la mémoire d'origine de la fonction qui Je ne peux le faire qu'en déréférençant le pointeur sur le tableau original 2d char. Je ne comprends pas pourquoi je devrais avoir une faute de seg sur la deuxième fois, et je serais reconnaissant pour tout conseil.

Un grand merci

Joe

Répondre

4

Essayez:

printf("%s\n", (*memory_ref)[i]); 

La version actuelle est équivalente à

*(*(memory_ref + i)); 

En effet, l'opérateur [] a une priorité plus élevée que le déréférencement * . Ce qui signifie que lorsque i est supérieur à 0 vous essayez de lire la mémoire après la char*** temporaire memory_ref

La deuxième version est égale à (*memory_ref)[i] ce qui signifie que vous serez indexation de la mémoire correcte.

EDIT: La raison pour laquelle il travaille sur la première itération est parce que:

*(*(memory_ref + 0)) == *((*memory_ref) + 0) 
+0

Cela fonctionne. Merci beaucoup. Je ne sais pas pourquoi si. Je suppose que les crochets permettent l'opération de déréférencement de terminer avant de tenter d'accéder au résultat de l'opération déréférencement. encore que n » t expliquer le comportement de la première chaîne dans l'impression de tableau si.Pourquoi n'ai-je pas segmenter la faute première fois? Un grand merci Joe – Joe

+0

Voir ma réponse éditée, '[]' a plus de priorité que '* '. –

+0

@Joe quant à pourquoi cela a fonctionné sur la première fois, voir ma réponse éditée. –

2

Cela ressemble à une question de priorité. Le [] est évalué en premier et le * deuxième. Ce dont vous avez besoin est quelque chose comme ce qui suit pour votre premier exemple de code ...

printf("%s\n", (*memory_ref)[i]); 
1

La solution rapide est d'utiliser

printf("%s\n", (*memory_ref)[i]); 

Mais je soupçonne que vous avez un problème dans les lignes

memory[0] = "Mem 0"; 

Ils ne copient pas la chaîne « Mem 0 » dans votre mémoire tableau. Ils font mémoire [i] pointent vers la chaîne.

Vous devez copier explicitement les données à l'aide strncpy

par exemple car s = "Mem 0"; strncpy (mémoire 1, s, max (strlen (s) + 1, 29)) // max de 30 = (29 char + '\ 0' car c'est la longueur de ligne allouée - mieux vaut # définir cela comme constante