2010-11-25 4 views
1

Je suis un noob en c, et j'ai ce code qui ne fonctionne pas correctement car une mauvaise allocation de mémoire que je fais pour un pointeur char **. S'il te plait peux-tu aider? Merci beaucoup d'avance. Code:c pointeur vers l'allocation de la mémoire du pointeur

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



struct node_t { 

struct tuple_t *tuple; //Entrada na lista 

struct node_t *next; //o node seguinte da lista 

}; 

struct tuple_t { 
long timestamp; /* instante de criacao do tuplo*/ 
int n_fields; /* numero de campos deste tuplo */ 
char **fields; /* array com campos do tuplo */ 
/* 4 + 4 + 4 bytes?? */ 
}; 

char ** split_str(char [], char **, const char *); 

struct node_t *node_create(void *node_data){ 

struct node_t *node = NULL; 
node = (struct node_t *)malloc(sizeof(struct node_t)); 
if(!node){ 
    printf("Erro ao criar um node!\n"); 
    return NULL; 
} 

node->tuple = (struct tuple_t *)malloc(sizeof(struct tuple_t)); 
if(!node->tuple){printf("Erro ao criar o node->tuple\n"); free(node); return NULL;} 

node->tuple->fields = (char **)malloc(strlen((char *) node_data) * sizeof(char *)); 
if(!node->tuple->fields){ printf("Erro ao criar o node->tuple->node_fields\n"); free(node->tuple); free(node); return NULL; } 

char **array; 
const char *sep=" "; 
char *s = (char *)node_data; 
char arr[strlen(s)]; 
int i = 0; 
while(arr[i++]=s[i]); 

array = split_str(arr,array, sep); 

i = 0; 
while(array[i]){ 
    node->tuple->fields[i] = (char *)malloc((strlen(array[i])) * sizeof(char)); 
    if(!node->tuple->fields[i]){ 
    printf("Erro ao alocar memoria em node_create() para node->tuple->fields[i]\n"); 
    return NULL; 
    } 
    node->tuple->fields[i] = array[i]; 
// printf("array[i]=%s\n",array[i]); 
// printf("node->tuple->fields[i]=%s\n",node->tuple->fields[i]); 
    i++; 

} 

node->tuple->n_fields = i; 
node->tuple->timestamp = 0L; 
node->next = NULL; 

return node; 
} 

char** split_str(char writablestring[],char **array, const char *sep){ 

array = malloc(strlen(writablestring) + 1); 

if(! array){printf("Erro ao alocar memoria para o array em split\n"); return NULL;} 

char *token = strtok(writablestring, sep); 

int i=0; 
while(token != NULL) 
{ 
    array[i] = malloc(strlen(token)+1); 
    if(!array[i]) 
    return NULL; 
    array[i] = token; 
    token = strtok(NULL, " "); 
    i++; 
} 

return array; 
} 


int main(int argc, char** argv) 
{ 

void * n_data = "hello 123 ploc"; 

struct node_t * node = node_create(n_data); 
printf("node->num_fields=%d\n", node->tuple->n_fields); 
int i=0; 

while(node->tuple->fields[i]){ 
    printf("node->tuple->fields[%d]=%s\n",i,node->tuple->fields[i]); 
    i++; 
} 

return 0; 
} 

Code de fin.

+0

Je vois plusieurs choses peu précis. Par exemple, en passant 'node_data' en tant que 'void *', en allouant de la mémoire pour les champs 'node-> tuple-> [i]' puis en l'écrasant immédiatement (peut-être vous vouliez dire 'memcpy' ou' strcpy'), et les fuites de mémoire . Mais cela aiderait à expliquer ce que vous essayez de faire globalement et dans chaque partie. –

+0

désolé je n'avais pas le temps de répondre ... fondamentalement, je voulais ajouter la chaîne fractionnée dans le champ 'fields' de tuple_t struct. Mais tu as raison, le code est en désordre. Heureusement, maintenant j'ai une solution;) – alinnemet

Répondre

1

Votre fonction split_str() renvoie des pointeurs dans writablestring, qui correspond au tableau arr dans node_create(). Vous copiez ensuite ces pointeurs dans node->tuple->fields[i] - mais le tableau arr n'existera pas après la fermeture de la fonction node_create() - ces pointeurs ne seront donc plus valides. Au lieu de cela, vous devez copier la chaîne retournée dans la mémoire que vous avez allouée (cela montre également comment vous pouvez utiliser une boucle for() à la place de votre while(), et vous devez également libérer la mémoire allouée dans split_str()):

for (i = 0; array[i]; i++) { 
    node->tuple->fields[i] = malloc(strlen(array[i]) + 1); 

    if (!node->tuple->fields[i]){ 
     printf("Erro ao alocar memoria em node_create() para node->tuple->fields[i]\n"); 
     return NULL; 
    } 

    strcpy(node->tuple->fields[i], array[i]); 
} 

free(array); 

en outre, votre code suppose que le tableau retourné par split_str() sera mis fin par un NULL, mais la fonction ne garantit pas. La fonction a de nombreux autres problèmes (taille incorrecte est passé à malloc(), fuite de mémoire causée par inutiles malloc()) - si vous avez besoin de le réparer aussi:

char **split_str(char writablestring[], const char *sep) 
{ 
    char **array = malloc(strlen(writablestring) * sizeof array[0]); 

    if(!array) { 
     printf("Erro ao alocar memoria para o array em split\n"); 
     return NULL; 
    } 

    char *token = strtok(writablestring, sep); 
    int i; 

    for (i = 0; (array[i] = token) != NULL; i++) { 
     token = strtok(NULL, " "); 
    } 

    return array; 
} 

(Notez que array n'a pas besoin d'être passé en paramètre - il est de toute façon immédiatement écrasé, donc je l'ai transformé en une variable locale).


Une fois que vous avez fait cela, vous remarquerez peut-être qu'il n'y a vraiment aucune raison d'attribuer array à split_str(), pour copier son contenu node->tuple->fields puis le libérer. Vous pouvez aussi bien passer le tableau node->tuple->fields à split_str() et l'écrire directement dans le tableau. Il pourrait alors revenir le nombre de chaînes affectées - qui ressemblerait à ceci:

int split_str(char [], char **, const char *); 

struct node_t *node_create(void *node_data) 
{ 
    struct node_t *node = NULL; 
    char *s = node_data; 
    size_t slen = strlen(s); 

    node = malloc(sizeof *node); 
    if (!node) { 
     printf("Erro ao criar um node!\n"); 
     return NULL; 
    } 

    node->tuple = malloc(sizeof *node->tuple); 
    if (!node->tuple) { 
     printf("Erro ao criar o node->tuple\n"); 
     free(node); 
     return NULL; 
    } 

    node->tuple->fields = malloc(slen * sizeof node->tuple->fields[0]); 
    if (!node->tuple->fields) { 
     printf("Erro ao criar o node->tuple->node_fields\n"); 
     free(node->tuple); 
     free(node); 
     return NULL; 
    } 

    char arr[slen + 1]; 
    strcpy(arr, s); 

    int i = split_str(arr, node->tuple->fields, " "); 

    node->tuple->n_fields = i; 
    node->tuple->timestamp = 0L; 
    node->next = NULL; 

    return node; 
} 

int split_str(char writablestring[], char **array, const char *sep) 
{ 
    char *token = strtok(writablestring, sep); 
    int i; 

    for (i = 0; token != NULL; i++) { 
     array[i] = malloc(strlen(token) + 1); 
     if (!array[i]) { 
      printf("Erro ao criar o array[i]\n"); 
      break; 
     } 
     strcpy(array[i], token); 
     token = strtok(NULL, " "); 
    } 

    return i; 
} 
+0

thx beaucoup mec, ces conseils rendent les choses plus claires maintenant ... – alinnemet

0

Essayez quelque chose comme ceci:

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


struct tuple_t 
{ 
    long timestamp; /* instante de criacao do tuplo*/ 
    int n_fields; /* numero de campos deste tuplo */ 
    char** fields; /* array com campos do tuplo */ 
}; 

struct node_t 
{ 
    struct tuple_t* tuple; //Entrada na lista 
    struct node_t* next; //o node seguinte da lista 
}; 


char** split_str(const char *, const char *, int *); 
void node_destroy(struct node_t*); 

struct node_t* node_create(char* node_data) 
{ 
    struct node_t* node = (struct node_t *) malloc(sizeof(struct node_t)); 
    if(!node) 
    { 
     printf("Erro ao criar um node!\n"); 
     return NULL; 
    } 

    node->tuple = (struct tuple_t *) malloc(sizeof(struct tuple_t)); 
    if(!node->tuple) 
    { 
     printf("Erro ao criar o node->tuple\n"); 
     node_destroy(node); 
     return NULL; 
    } 

    node->tuple->timestamp = 0L; 

    node->tuple->fields = split_str(node_data, " ", &(node->tuple->n_fields)); 
    if(!node->tuple->fields) 
    { 
     printf("Erro ao criar o node->tuple->node_fields\n"); 
     node_destroy(node); 
     return NULL; 
    } 

    node->next = NULL; 

    return node; 
} 

void node_destroy(struct node_t* node) 
{ 
    if(node) 
    { 
     if(node->tuple) 
     { 
      if(node->tuple->fields) 
      { 
       for(int i = 0; i < node->tuple->n_fields; ++i) 
        free(node->tuple->fields[i]); 

       free(node->tuple->fields); 
      } 

      free(node->tuple); 
     } 

     free(node); 
    } 
} 

char** split_str(const char* str, const char* sep, int* found) 
{ 
    if (found) *found = 0; 

    int len = strlen(str); 

    char** array = (char**) malloc(len * sizeof(char*)); 
    if(!array) 
    { 
     printf("Erro ao alocar memoria para o array em split\n"); 
     return NULL; 
    } 

    ++len; 

    char* writablestring = (char*) malloc(len); 
    if(!array) 
    { 
     printf("Erro ao alocar memoria para writeablestring em split\n"); 
     free(array); 
     return -1; 
    } 

    strncpy(writablestring, str, len); 

    char* token = strtok(writablestring, sep); 
    int i = 0; 

    while(token) 
    { 
     len = strlen(token) + 1; 

     array[i] = (char*) malloc(len); 
     if(!array[i]) 
     { 
      printf("Erro ao alocar memoria para o array item em split\n"); 

      free(writeablestring); 
      for(int j = 0; j < i; ++j) 
       free(array[j]); 
      free(array); 
      return NULL; 
     } 

     strncpy(array[i], token, len); 
     ++i; 

     token = strtok(NULL, sep); 
    } 

    free(writeablestring); 

    if(found) *found = i; 
    return array; 
} 


int main(int argc, char** argv) 
{ 
    char* n_data = "hello 123 ploc"; 

    struct node_t* node = node_create(n_data); 
    if(node) 
    { 
     printf("node->tuple->n_fields=%d\n", node->tuple->n_fields); 

     for(int i = 0; i < node->tuple->n_fields; ++i) 
      printf("node->tuple->fields[%d]=%s\n", i, node->tuple->fields[i]); 

     node_destroy(node); 
    } 

    return 0; 
} 
+0

mec! Tha lot man ... mon code était vraiment crapp par rapport à celui-ci ... agréable et lisse. – alinnemet

Questions connexes