如何从包含动态创建的字符串数组的结构中释放内存?

时间:2011-08-23 10:16:46

标签: c data-structures struct cstring

我有一个结构,除其他外,必须包含动态创建的字符串和动态创建的字符串数组。但是,我发现之后很难释放这个结构,因为它给了我运行时错误。

所以问题是:

到目前为止,我甚至无法释放字符串。为什么呢?

如何在此结构中创建字符串的动态“数组”?

#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 个答案:

答案 0 :(得分:2)

首先,构造函数是错误的。它将为您提供计算机上指针的大小,因此非常从那时起您使用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);
}

答案 1 :(得分:0)

有两件事让人想起:

  1. top->name=calloc(1,strlen(name));在这里,您应该为空终止符分配一个字节,或者在调用strcpy时创建一个未终止的字符串。 (此外,name中的本地constructor()应声明为const char *。)

  2. if(top->coords!=NULL) { free(top->coords); }您永远不会将coords初始化为零。因此,如果您只是在新建的结构上调用destructor,那么您很可能会调用无效的free()