Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bus error in C struct

Tags:

c++

c

struct

bus

This is a code I testing to copying struct.

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 typedef struct emp_struct {
 5     char *name;
 6     int employee_no;
 7     float salary,
 8           tax_to_date;
 9 } Employee;
 10 
 11 typedef Employee Database[10];
 12 
 13 Database people = {
 14     {"Fred", 10, 10000, 3000},
 15     {"Jim", 9, 12000, 3100.5},
 16     {"Fred", 13, 1000000, 30},
 17     {"Mary", 11, 170000, 4000},
 18     {"Judith", 45, 130000, 50000},
 19     {"Nigel", 10, 5000, 1200},
 20     {"Trevor", 10, 20000, 6000},
 21     {"Karen", 10, 120000, 34000},
 22     {"Marianne", 10, 50000, 12000},
 23     {"Mildred", 10, 100000, 30000}
 24 };
 25 
 26 int main () {
 27     // array act like pointer, thus pointing + pointing = ERROR
 28     printf("people[1]->name: ERROR\n");
 29     // jump its memory amount of struct size
 30     printf("(people+1)->name:%s\n",(people+1)->name);
 31     // array works as a pointer
 32     printf("people[3].name:%s\n",people[3].name);
 33 
 34     /* Is it possible to assign struct to struct? */
 35     printf("\nAssigning struct to struct\n");
 36     Employee temp;
 37     temp = *(people+5); // Nigel Record
 38     printf("Name: %s\n",temp.name);
 39     // exchange
 40     strcpy(temp.name, "Ahn");
 41     printf("Changed: %s\n",temp.name);
 42     printf("Original: %s\n",people[5].name);
 43 
 44     return 0;
 45 }

When I tried to strcpy(new, string) in line 40, then it throws out Bus error: 10.

I expected that value Changed and Original are same in line 41 and 42. But it would not work. What is the problem of assigning?

I knew that Bus error:10 is occurred by lack of assignment space. But my name field in struct is pointer (in line 5). If I changed name field like

 char name[100];

It works properly and Changed and Original value are different! Even though I assigned that as a pointer.

What is the problem of this struct assigning?

like image 451
sogo Avatar asked Dec 18 '13 02:12

sogo


2 Answers

temp.name is a pointer to char. After the copy temp = *(people+5);, temp.name is pointing to the bytes containing "Nigel".

So far, no problem. But you can't use that pointer as the output for strcpy(); strcpy will try to overwrite it, and it's stored in read-only memory.

You can do this:

temp.name = "Ahn";

... since all that you are doing here is changing the pointer (temp.name) to point to a different area of memory which is set up in advance to contain "Ahn".

This is actually nothing to do with struct copying. You will have the same problem if you try to do strcpy(people[3].name, "Ahn")

like image 66
greggo Avatar answered Sep 19 '22 16:09

greggo


When you declared the Database record, all the names(Fred, Jim, Fred ...) were put in the read-only memory of the data segment and the name character pointer pointed to their starting addresses.

When you do strcpy(temp.name, "Ahn");, you are trying to write in the read-only. Trying to write into read-only memory will cause a bus error.

The solution would be to allocate memory for the name and then do the strcpy. Also a good programming practice is to use strncpy instead of strcpy

like image 26
user376507 Avatar answered Sep 22 '22 16:09

user376507