Reputation: 111
I have a problem where I have to copy a structure and add it to new memory then free the old memory. Then I have to increment to create space for new memory and add again. I thought I had the logic correct but I keep getting a segmentation fault. I can't figure out where I am going wrong.
Here is a copy of my 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;
Here is a copy of my add function:
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);
}
And here is my call to function:
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
}
Upvotes: 0
Views: 107
Reputation: 6776
In your case the structure struct childrensBook
contains pointers to strings. If your want deep copy of that object you need also copy internal strings.
However, since you are using constant lengths for all string fields it is possible to use all string elements as char
arrays. In that case the entire content will be stored in one piece of memory:
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;
Upvotes: 0
Reputation: 133569
I see multiple errors here:
free(book)
frees the dynamically allocated struct book
but not its dynamically allocated fields (book->title
and such things must be freed too)memcpy
to book->author
and other char*
fields but these fields haven't been dynamically allocated, maybe you wanted to do book->title = strdup("literal")
,memcpy(book1, book, sizeof *book1)
has at least two errors: first you hare coping sizeof *book1 bytes
, which is the size of a pointer, not the whole struct. Then you are copying fields which doesn't contain primitive types but pointers which would then share ownership between two books, you should copy each single dynamically allocated field.Just to give some code to start with:
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);
...
}
Upvotes: 2
Reputation: 16607
memcpy
do not add null terminator. So either add '\0'
after memcpy
manually or increase number of byte in memcpy
.
Do this -
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);
And because your book->title
is not null terminated , therefore , fprintf
with specifier %s
gives seg fault.
And if you use fixed memory in malloc
(i.e 100
) , why use it ? Declare them as arrays -
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);
Then you won't have take tension to free
it.
Note - If you use malloc
then as also mentioned in comment , please don't cast result of malloc
.
Upvotes: 1
Reputation: 234725
Don't forget to copy over the null-terminators on your string literals:
You need to use "Little Simon", 13
instead etc.: "Little Simon"
is not as little as you think. It occupies 13 bytes, not 12.
Else your fprintf
will overrun past your string, with disastrous results: a segmentation fault being one possibility.
Upvotes: 0