2013-12-18 3 views
6

Это код, который я тестирую для копирования структуры.Ошибка шины в C 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 } 

Когда я попытался зЬгсру (новый, строка) в строке 40, то он выбрасывает ошибку шины: 10.

Я ожидал, что значение Изменено и Оригинал одинаковы в строке 41 и 42. Но это не будет работать. В чем проблема назначения?

Я знал, что ошибка шины: 10 возникает из-за нехватки места назначения. Но мое имя Поле в структуре является указателем (в строке 5). Если я изменил имя поля как

char name[100]; 

Он работает правильно и Изменено и Оригинал значения отличаются! Хотя я назначил это как указатель.

В чем проблема с назначением этой структуры?

+5

Вы никогда не выделяете память для 'temp.name', а значение в базе данных указывает на то, что следует считать постоянными данными. Если вы попытаетесь написать в эту область, все может случиться; ваша ОС, по-видимому, просто выбрала запуск SIGBUS. – cHao

+0

@cHao. Я уже пробовал имя temp-> name как присвоение указателя, но он выбрасывает ссылку на ошибку. Тогда имеет смысл назначить поле имени * в поле «malloc». – Sogo

+1

@cHao Я попытался использовать 'char * name = (char *) malloc (sizeof (char) * 100);' и он работает. Ты прав. Я думаю, что неопределенное назначение памяти всегда происходит ошибка. Благодаря! – Sogo

ответ

3

temp.name - указатель на символ. После копии temp = *(people+5);, temp.name указывает на байты, содержащие «Найджел».

До сих пор никаких проблем. Но вы не можете использовать этот указатель как вывод для strcpy(); strcpy попытается перезаписать его, и он будет сохранен в постоянной памяти.

Вы можете сделать это:

temp.name = "Ан";

... так как все, что вы здесь делаете, меняет указатель (temp.name), чтобы указать на другую область памяти, которая настроена заранее, чтобы содержать «Ahn».

Это не имеет никакого отношения к структурированию. У вас будет та же проблема, если вы пытаетесь сделать strcpy(people[3].name, "Ahn")

1

Когда вы объявили о записи базы данных, все имена (Фред, Джим, Фред ...) были помещены в read-only памяти сегмента данных и name указатель на указатель указывал на их начальные адреса.

Когда вы делаете strcpy(temp.name, "Ahn");, вы пытаетесь писать в режиме только для чтения. Попытка записать в память read-only вызовет ошибку шины.

Решение было бы выделить память для name, а затем сделать strcpy. Также хорошей практикой программирования является использование strncpy вместо strcpy

Смежные вопросы