2015-09-30 3 views
0

J'ai un problème où je dois copier une structure et l'ajouter à la nouvelle mémoire puis libérer l'ancienne mémoire. Ensuite, je dois incrémenter pour créer de l'espace pour la nouvelle mémoire et ajouter à nouveau. Je pensais que j'avais la logique correcte mais je continue à avoir une erreur de segmentation. Je ne peux pas comprendre où je vais mal.Comment copier une structure?

Voici une copie de ma structure:

struct childrensBook *book = (struct childrensBook *) malloc(sizeof(struct childrensBook));  //Structure of book #1 

book->title = (char *)malloc(100);     //allows memmory of 100 characters             
book->author = (char *)malloc(100);    //allows memmory of 100 characters 
book->publisher = (char *)malloc(100);    //allows memmory of 100 characters 
book->copyright = 0; 
book->price = 0; 

Voici une copie de ma fonction ajouter:

int addRecord() 
{ 
    int headptr = 0; 
    struct childrensBook *book = malloc(sizeof(struct childrensBook));   //get book structure 
    struct childrensBook *book1 = malloc(sizeof(struct childrensBook));   //create structure book1 
    memcpy(book->title, "We're Going on a Bear Hunt", 26);      //populate fields of book 
    memcpy(book->author, "Michael Rosen", 13);         //populate fields of book 
    memcpy(book->publisher, "Little Simon", 12);        //populate fields of book 
    book->copyright = 1989;             //populate fields of book 
    book->price = 7.99;              //populate fields of book 
    memcpy(book1, book, sizeof *book1);      //copy fields of book to book 1 
    free(book); 
} 

Et voici mon appel à la fonction:

else if(x==4) 
{ 
    addRecord(); 
    fprintf(stderr, "You have added the record: %s\n", book->title); 
    free(book); 
    moveptr++; //here to incrememnt for new space. This is a globaal variable 
} 
+0

Ne pas jeter le résultat de 'malloc' et amis C. (Notez que vous êtes déjà inconsistenly Renversement/pas coulée dans votre code) . Et ** toujours ** vérifier le résultat des fonctions qui pourraient rencontrer une erreur: 'malloc' peut renvoyer un pointeur _null! – Olaf

+0

Utilisez 'strncpy' pour copier des chaînes! Et n'utilisez pas de nombres magiques! Et utilisez l'affectation normale pour copier une 'struct'. 'memcpy' inhibe la vérification de type. – Olaf

+0

Sur quelle ligne se trouve un défaut de segmentation? Ceci est très important et très facile à diagnostiquer, donc vous devriez le faire afin d'obtenir de bonnes réponses. – anatolyg

Répondre

0

N'oubliez pas de copier les terminaisons nulles sur vos littéraux de chaîne:

Vous devez utiliser "Little Simon", 13 à la place, etc .: "Little Simon" n'est pas aussi peu que vous le pensez. Il occupe 13 octets, pas 12.

Sinon, votre fprintf dépassera votre chaîne, avec des résultats désastreux: un défaut de segmentation étant une possibilité.

1

memcpy ne pas ajouter de terminateur nul. Donc, soit ajouter '\0' après memcpy manuellement ou augmenter le nombre d'octets dans memcpy.

faire -

memcpy(book->title, "We're Going on a Bear Hunt", 26); // or use strncpy so it will add null terminator   
memcpy(book->author, "Michael Rosen", 14);         
memcpy(book->publisher, "Little Simon", 13);        

Et parce que votre book->title est nulle fin donc pas fprintf avec spécificateur %s donne faute de SEG.

Et si vous utilisez la mémoire fixe dans malloc (c'est-à-dire 100), pourquoi l'utiliser? Déclarer les sous forme de tableaux -

book->title = (char *)malloc(100);   // in struct declare title as char title[100]    
book->author = (char *)malloc(100);   // similar with rest.  
book->publisher = (char *)malloc(100);    

vous ne serez pas avoir à prendre la tension free il.

Remarque - Si vous utilisez malloc puis comme également mentionné dans un commentaire, s'il vous plaît ne nécessitent pas de jeter malloc.

+0

'strdup()' est beaucoup plus clair et moins sujette aux erreurs que 'malloc()' suivi de 'memcpy()' avec des nombres magiques. –

+0

@AndrewHenle Il est clairement, je mentionne juste la cause de la faute de segmentation. – ameyCU

+0

Les nombres magiques dans la question originale sont effrayants. –

2

Je vois plusieurs erreurs ici:

  • free(book) libère la dynamique allouée struct book mais pas ses champs alloués dynamiquement (book->title et ces choses doivent être libérés aussi)
  • vous appelez memcpy à book->author et d'autres char* champs mais ces champs n'ont pas été alloués dynamiquement, peut-être que vous vouliez faire book->title = strdup("literal"),
  • memcpy(book1, book, sizeof *book1) a au moins deux erreurs: d'abord vous avez coping sizeof *book1 bytes, qui est la taille d'un pointeur, pas la structure entière. Ensuite, vous copiez des champs qui ne contiennent pas de types primitifs mais des pointeurs qui partageraient alors la propriété entre deux livres, vous devez copier chaque champ alloué dynamiquement.

Juste pour donner un peu de code pour commencer:

void free_book(struct book* b) { 
    free(b->title); 
    free(b->author); 
    ... 
    free(b); 
} 

struct* book dupe_book(struct book* source) { 
    struct book* dest = malloc(sizeof(struct book)); 
    dest->price = source->price; 
    dest->author = strdup(source->author); 
    ... 
} 
0

Dans votre cas, la structure struct childrensBook contient des pointeurs vers des chaînes. Si vous voulez une copie profonde de cet objet, vous devez également copier les chaînes internes. Cependant, étant donné que vous utilisez des longueurs constantes pour tous les champs de chaîne, il est possible d'utiliser tous les éléments de chaîne sous forme de tableaux char. Dans ce cas, la totalité du contenu sera stocké dans un morceau de mémoire:

struct childrensBook { 
    char title[100]; 
    char author[100]; 
    char publisher[100]; 
    int copyright; 
    int price; 
} 

/* the structure content may be written as follows */ 
strcpy(book->title, "We're Going on a Bear Hunt"); 

/* structure copy by direct assignment */ 
*book1 = *book;