2017-07-14 1 views
-1

Pourquoi ce programme entraîne-t-il une erreur de segmentation? J'essaie d'avoir un tableau de pointeurs qui est dynamiquement alloué de la mémoire afin que je puisse avoir un tableau de chaînes.Pourquoi mon programme génère-t-il une erreur de segmentation lors de l'affectation de la mémoire à un double pointeur C

J'ai cherché des problèmes similaires comme How to pass a double pointer to a function without segmentation fault C language

S'il vous plaît expliquer pourquoi il SEG-formation de failles

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

void mem_alloc(char* p, char** dp); 

int entries = 0; 
int mem_allocated = 0; 

int main() { 

    char* p = "ksdfahj93qhf9"; 
    char* p1 = "siodfnrieopq"; 
    char* p2 = "erf9ih94gri9g"; 

    char** dp = NULL; 

    mem_alloc(p, dp); 
    mem_alloc(p1, dp); 
    mem_alloc(p2, dp); 

    for(int i = 0; i < entries; i++) { 

     printf("%s", dp[i]); 
    } 
} 
void mem_alloc(char *p, char** dp) { 
    if(entries == mem_allocated) 
     if(mem_allocated == 0) 
      mem_allocated = 3; 
    void** temp = realloc(dp, mem_allocated * (sizeof(p))); 
    if(!temp) 
     perror("Memory allocation failed!"); 

    dp = (char**) temp; 
    strcpy(dp[entries++], p); 

} 
+0

Je vois un peu de désordre sans déréférencer ce qui devrait être et déréférencer ce qui ne devrait pas être ... –

+0

À quelle ligne est-ce que seg-faulting? – klutt

+0

Vous ne pouvez pas mettre à jour le côté appelant 'dp' à l'intérieur de la fonction en tant qu'argument (' char ** dp'). corriger comme [this] (http://ideone.com/0Ft10C) – BLUEPIXY

Répondre

1

Dans votre fonction mem_alloc vous modifiez le paramètre de la fonction dp. Cette modification n'est pas visible en dehors de la fonction. Par conséquent, le dp dans main ne change jamais et est toujours défini sur NULL.

Vous devez transmettre l'adresse de cette variable à la fonction, puis dans la fonction, vous déréférencer ce pointeur pour le modifier.

Vous fonctionnez devient:

void mem_alloc(char *p, char ***dp) { 
    if(entries == mem_allocated) 
     if(mem_allocated == 0) 
      mem_allocated = 3; 
    char **temp = realloc(*dp, mem_allocated * (sizeof(p))); 
    if(!temp) 
     perror("Memory allocation failed!"); 

    *dp = temp; 
    (*dp)[entries++] = strdup(p); // space also needs to be allocated for the new string 
} 

Et vous l'appelez comme ceci:

mem_alloc(p, &dp); 
+0

Plutôt que d'ajouter une étoile supplémentaire dans la fonction, je supprimerais l'étoile dans le 'principal' ... –

+0

' void ** temp = ... 'devrait être' void * temp = ... '. De cette façon, la distribution ici: '* dp = (char **) temp;' peut être supprimée. – alk

+0

@alk En fait, il est plus logique de le faire 'char **', puisque c'est ce à quoi il est assigné et il supprime la distribution. Édité. – dbush

0

Deux erreurs. Le premier est celui mentionné par dbush. Deuxièmement, vous n'allouez pas d'espace pour votre chaîne avant de la copier. Vous pouvez utiliser strndup() au lieu de strcpy().

+0

Merci pour votre aide. Puis-je demander, pourquoi ai-je besoin d'allouer de la mémoire pour la chaîne si la variable 'dp' a déjà de la mémoire allouée pour un nouveau pointeur? Est-ce parce que 'p' sera détruit quand' mem_alloc' sera hors de portée? Désolé je suis nouveau à C. –

+0

Vous allouez d'abord la mémoire pour le tableau de pointeurs. Vous devez ensuite allouer de la mémoire pour chaque pointeur du tableau afin de contenir la chaîne que vous copiez. – Seth

+0

Je suis confus, parce que j'ai juste l'habitude d'assigner un littéral de chaîne à un pointeur char. Mais maintenant, je dois allouer de la mémoire au pointeur après l'allocation de la mémoire à la matrice de pointeurs? –