SegFault в динамически выделенном массиве структур, C

typedef struct {
  double x;
  double y;
  long out_x;
  long out_y;
} coords;

typedef struct {
  char name[FIGURE_LEN + 1];
  int coordcount, size_tracker;
  coords *coordinate;
} fig;

fig figure;
fig * figpoint;

это функции, которые вызываются из исходного файла parser.c.

void initialize_fig(int n, char * name, double x, double y,
                         fig *fig_point)
{
  printf("inside function\n");
  strncpy(fig_point[n].name, name, FIGURE_LEN + 1);
  fig_point[n].size_tracker = 1;
  fig_point[n].coordinate = malloc(sizeof(coords) * fig_point[n].size_tracker);
  assert(fig_point[n].coordinate != NULL);
  fig_point[n].coordcount = 0;
  fig_point[n].coordinate[fig_point[n].coordcount].x = x;
  fig_point[n].coordinate[fig_point[n].coordcount].y = y;
}

void create_FigArray(fig * fig_point, int fig_size)
{
  fig_point = malloc(sizeof(fig) * fig_size);
  assert(fig_point != NULL);
  fig_point = &figure
}

сначала я вызываю create_FigArray вот так...

create_FigArray(fig_point, 16);

у меня нет ошибки сегмента... но потом я звоню...

initialize_fig(0, Qe, 10.0000, 10.0000, fig_point);

параметры фактически передаются через переменные, но я просто хотел показать, что они являются правильными параметрами, и привести пример того, какие значения передаются. В любом случае это бьет

strncpy(fig_point[n].name, name, FIGURE_LEN + 1);

и останавливается.. здесь должен произойти segfault, но почему?!

пожалуйста, помогите, объясните и покажите, как обойти это. благодарю вас.


person wenincode    schedule 04.11.2012    source источник
comment
Пожалуйста, не редактируйте вопрос после того, как у вас есть ответы. Это очень сбивает с толку.   -  person mathematician1975    schedule 05.11.2012


Ответы (3)


Вы выделяете память, затем меняете указатель

fig_point = malloc(sizeof(fig) * fig_size); // allocate here
assert(fig_point != NULL);
fig_point = &figure;  // now you make fig_point point to something else

поэтому ваш указатель fig_point больше не указывает на вашу динамически выделенную память. Если вы затем сделаете это

fig_point[n]

вы обращаетесь к памяти или диапазону, поскольку figure не является массивом. Кроме того, вы передаете указатель fig_point в create_FigArray напрямую. Это создаст копию указателя, и, следовательно, любые изменения, которые вы вносите в этот аргумент, на самом деле являются только изменениями в copy. Это означает, что динамическая память, в которой хранится адрес, хранящийся в fig_array после возвращения create_FigArray, такая же, как и раньше - функция изменила только copy. Если вы хотите изменить указатель, вам нужно использовать аргумент двойного указателя для функции, а затем что-то вроде

void create_FigArray(fig** fig_point, int fig_size)
{
    *fig_point = malloc(sizeof(fig) * fig_size);
}
person mathematician1975    schedule 04.11.2012
comment
@user1787262 user1787262 Нет, не редактируйте вопрос!! Это очень сбивает с толку любого, кто пытается ответить на ваш вопрос. - person mathematician1975; 05.11.2012
comment
так скажем я изменил его так, чтобы фунц взял фиг** fig_point. мне нужно изменить все '.' операторы на '-›' - person wenincode; 05.11.2012

Я не знаю, но:

Сначала вы выделяете память для fig_point:

fig_point = malloc(sizeof(fig) * fig_size);

И после этого вы назначаете ему адрес фигуры, этого делать не надо.

fig_point = &figure;

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

figure = *fig_point;
person fonZ    schedule 04.11.2012
comment
Вы не можете присвоить адрес фигуры выделенной fig_point. - person fonZ; 05.11.2012
comment
@askmish, вот почему я разыменовываю fig_point ... cplusplus.com/doc/tutorial/pointers< /а> - person fonZ; 05.11.2012

  • В create_FigArray вы делаете это: fig_point = malloc(sizeof(fig) * fig_size); а потом это: fig_point = &figure; //figure is a global variable and this causes a memory leak

  • Вместо этого напишите это:

void create_FigArray(fig * fig_point, int fig_size)
{
  fig_point = malloc(sizeof(fig) * fig_size);
  assert(fig_point != NULL);
  fig_point = &figure;//Remove this line
}
  • В функции, из которой вы вызываете initialize_fig() или где-то еще, убедитесь, что выделенная память освобождена.

  • Сделайте все указатели NULL перед использованием и добавьте проверку аргументов NULL в функциях, работающих с указателями, и проверяйте указатели NULL перед использованием.

person askmish    schedule 04.11.2012