Как я могу освободить память из моей структуры, содержащей массив динамически создаваемых строк? - PullRequest
0 голосов
/ 23 августа 2011

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

Итак, вопросы:

Пока я не могу даже отпустить строку. Почему?

Как создать динамический «массив» строк внутри этой структуры?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

typedef struct { 
  unsigned int num;
  unsigned int* sizes;
  unsigned int* coords;
  char* name;
} TOPOLOGY;

TOPOLOGY * constructor() {
  char * name="Hardware Topology";
  TOPOLOGY * top=calloc(1,sizeof(TOPOLOGY *));
  top->num=0;
  top->name=calloc(1,strlen(name));
  strcpy(top->name,name);
  return top;
}

void destructor(TOPOLOGY * top) {
  if(top->sizes!=NULL) { free(top->sizes); }
  if(top->coords!=NULL) { free(top->coords); }
  if(top->name!=NULL) { free(top->name); } exit(0);
  if(top!=NULL) { free(top); }
}

void add(TOPOLOGY * top, unsigned int size) {
  top->num++;
  size_t s=top->num*sizeof(unsigned int*);
  top->sizes=realloc(top->sizes,s);
  top->coords=realloc(top->coords,s);
  top->sizes[top->num-1]=size;
}

void coords(TOPOLOGY * top, unsigned int coords[]) {
  int i;
  for(i=0;i<top->num;i++) {
    top->coords[i]=coords[i];
  }
}

void get(TOPOLOGY * top) {
  int i;
  for(i=0; i<top->num;i++) {
    printf("Dim: %d: %d\n",i,top->sizes[i]);
  }
}

void getcoords(TOPOLOGY * top) {
  int i;
  for(i=0;i<top->num;i++) {
    printf("Coord %d = %d\n",i,top->coords[i]);
  }
}

void setname(TOPOLOGY * top, char * name) {
  int s=sizeof(name);
  top->name=realloc(top->name,s);
  strcpy(top->name,name);
}


int main() {
  unsigned int c[4]={3,2,0,1};
  TOPOLOGY * top=constructor();
  add(top,1025);
  add(top,512);
  add(top,10);
  add(top,24);
  coords(top,c);
  get(top);
  getcoords(top);
  destructor(top);
  return 0;
}

Ответы [ 2 ]

2 голосов
/ 23 августа 2011

Во-первых, конструктор неверен. Он даст вам размер указателя на вашей машине, так что в значительной степени все, что вы делаете с top с этого момента, будет недопустимым .

TOPOLOGY * top=calloc(1,sizeof(TOPOLOGY *)); /* Wrong. */
                                        ^
top = calloc(1, sizeof(TOPOLOGY)); /* Better. */
top = calloc(1, sizeof(*top)); /* Even better. */

Второй

Везде, где вы calloc строки, вы должны использовать strlen(...) + 1.

top->name=calloc(1, strlen(name) + 1);
strcpy(top->name, name);

Или, немного сбоку, использовать strdup:

top->name = strdup(name); /* Does malloc and whatnot for you. */

Третий

Не проверяйте на NULL при освобождении. free(NULL).

совершенно законно
void destructor(TOPOLOGY * top)
{
    free(top->sizes);
    free(top->coords);
    free(top->name);
    free(top);
}
0 голосов
/ 23 августа 2011

На ум приходят две вещи:

  1. top->name=calloc(1,strlen(name)); Здесь вы должны выделить еще один байт для нулевого терминатора, или вы создадите неопределенную строку при вызове strcpy,(Также локальный name в constructor() должен быть объявлен как const char *.)

  2. if(top->coords!=NULL) { free(top->coords); } Вы никогда не инициализируете coords в ноль.Так что если вы просто вызываете destructor для только что созданной структуры, вы вполне можете называть недействительным free().

...