2017-09-11 1 views
1

Voici mon code. Je luttais pour savoir pourquoi strncpy() ne peux pas copier la chaîne dans un struct, puisque cela fonctionnait parfaitement dans ma précédente mission. En outre, j'ai deuxième question: supposons que j'ai un struct contient un autre struct, comment affecter la valeur à l'struct intérieur:Erreur de segmentation: 11 (causée par strncpy())

struct _field { 
    char fieldName[50]; 
    char fieldType[50]; 
    int fieldLength; 
}; 
struct _table { 
    char *tableFileName; 
    int reclen; 
    int fieldcount; 
    struct _field fields[100]; 
}; 

typedef enum { false, true } bool; 

bool loadSchema(struct _table *table) { 

    printf("%s\n", "*** LOG: Loading table fields..."); 

    FILE *fp = NULL; 
    char lines[1000]; 
    char s[2] = " "; 

    fp = fopen("in.txt", "r+"); 

    while (fgets(lines, sizeof(lines), fp) != NULL) { 
     char *token; 
     token = strtok(lines, s); 

     if (token != NULL) { 
      if (strcmp(token, "CREATETABLE") == 0) { 
       token = strtok(NULL, s); 
       if (token != NULL) { 
        token[strlen(token)-1] = '\0'; 
        strcat(token, ".bin"); 
        //table->tableFileName = token; // this line can write the value into struct 
        strncpy(table->tableFileName, token, 20);// this line cant write the value into struct 
       } 
       printf("*** LOG: Table name is [%s]\n", table->tableFileName); 
      } 
      /*if (strcmp(token, "ADD") == 0) { 
       token = strtok(NULL, s); 
       if (token != NULL) {  
        strncpy((*table).fields. fieldName, token, 50);  
       }// Q2: how to give a value into a struct of a struct? 
      }*/ 
     } 
    } 
    return 1; 
} 

fichier d'entrée ressemble à ceci:

CREATETABLE people 
ADD id char 50 
ADD lname char 50 
+0

O/T, mais recommandez '#include stdbool.h' plutôt que votre propre' typedef' – yano

+0

'table-> tableFileName' pointe vers rien (ou au moins l'allocation n'est pas affichée). –

+2

D'où vient le '20'? Ça aurait dû être un indice que vous venez de le faire sortir de nulle part. La longueur passée à strncpy doit être la taille du tampon de destination. Dans votre cas c'est 0 puisque vous n'avez jamais alloué d'espace. – stark

Répondre

0

Vous obtenez l'erreur de segmentation car dans le code, vous essayez d'accéder à la table de pointeurs pour laquelle leur mémoire n'est pas allouée, donc il pointe vers null. D'où le crash. solution au problème serait de copier ces lignes

table = (struct _table*)(malloc (sizeof(struct _table))); 

table->tableFileName = (char *)(malloc (sizeof(char) * 20)); 
strncpy(table->tableFileName, token, 20); 

et souvenez-vous de les libérer. pour répondre à votre deuxième question, vous avez juste besoin d'attribuer une valeur directement outer_struct.innerstruct.field1 = valeur outer_struct.innerstruct.field2 = valeur

ou si la structure interne est un pointeur que vous devez initialiser la mémoire pour elle d'abord et alors vous pouvez assigner ou utiliser directement memcpy.

+0

Votre explication est presque correcte: le membre 'tableFileName' pourrait ne pas être' NULL' si 'table' pointe vers une structure non initialisée: un objet avec un stockage automatique dans la portée de l'appelant ou un objet alloué avec' malloc() '. 'table' peut même être un pointeur invalide ... – chqrlie

+0

Oui, il est préférable de memset la mémoire après allocation en utilisant malloc. Mais dans ce scénario, nous n'avons pas la mémoire allouée pour la structure _table elle-même et dans ma solution j'alloue de la mémoire et lui attribue la valeur de jeton afin qu'elle soit sûre jusqu'à ce que d'autres variables non initialisées soient accédées. –

+0

L'utilisation de 'calloc()' est une approche plus sûre et plus simple. – chqrlie

0

Question 1: Vous Essayez de copier dans une chaîne qui n'a pas d'espace alloué. table-> tableFilename est juste un pointeur. Vous devrez soit allouer de l'espace dynamiquement ou déclarer une largeur fixe du tableau. L'affectation table-> tableFilename = token fonctionnera correctement car elle attribue simplement une valeur au pointeur, elle n'essaie pas de copier des données dans un espace non alloué.

Question 2: Dans votre table de déclaration -> _ fields est un tableau de sorte que vous avez besoin d'indexer une instance spécifique pour assigner une valeur à ses membres. Par exemple. table-> fields [0] .fieldName.

+0

* table d'affectation-> tableFilename = token fonctionnera bien * - elle ira aux mauvaises herbes une fois hors de cette fonction. –