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

C 如何从包含动态创建字符串数组的结构中释放内存?,c,data-structures,struct,cstring,C,Data Structures,Struct,Cstring,我有一个结构,其中必须包含一个动态创建的字符串和一个动态创建的字符串数组。然而,我发现以后很难释放这个结构,因为它会给我运行时错误 因此,问题是: 到目前为止,我甚至无法释放字符串。为什么? 如何在此结构中创建字符串的动态“数组” #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> typedef struct { unsigned i

我有一个结构,其中必须包含一个动态创建的字符串和一个动态创建的字符串数组。然而,我发现以后很难释放这个结构,因为它会给我运行时错误

因此,问题是:

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

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

#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;
}
#包括
#包括
#包括
#包括
类型定义结构{
无符号整数;
无符号整数*大小;
无符号整数*坐标;
字符*名称;
}拓扑结构;
拓扑*构造函数(){
char*name=“硬件拓扑”;
拓扑*top=calloc(1,sizeof(拓扑*);
top->num=0;
top->name=calloc(1,strlen(name));
strcpy(顶部->名称,名称);
返回顶部;
}
无效析构函数(拓扑*顶部){
如果(顶部->大小!=NULL){free(顶部->大小);}
如果(top->coords!=NULL){free(top->coords);}
如果(top->name!=NULL){free(top->name);}退出(0);
如果(top!=NULL){free(top);}
}
void add(拓扑*top,无符号整数大小){
top->num++;
size_t s=top->num*sizeof(unsigned int*);
顶部->尺寸=realloc(顶部->尺寸,s);
顶部->坐标=realloc(顶部->坐标,s);
顶部->尺寸[顶部->数值-1]=尺寸;
}
无效坐标(拓扑*顶部,无符号整数坐标[]){
int i;
对于(i=0;inum;i++){
top->coords[i]=coords[i];
}
}
void get(拓扑*顶部){
int i;
对于(i=0;inum;i++){
printf(“尺寸:%d:%d\n”,i,顶部->尺寸[i]);
}
}
void getcoords(拓扑*顶部){
int i;
对于(i=0;inum;i++){
printf(“坐标%d=%d\n”,i,top->coords[i]);
}
}
void setname(拓扑*顶部,字符*名称){
int s=sizeof(名称);
top->name=realloc(top->name,s);
strcpy(顶部->名称,名称);
}
int main(){
无符号int c[4]={3,2,0,1};
拓扑*top=constructor();
增加(顶部,1025);
添加(顶部,512);
增加(前10名);
增加(顶部,24);
coords(顶部,c);
得到(顶部);
getcoords(顶部);
析构函数(顶部);
返回0;
}

想到两件事:

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

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


  • 首先,构造函数是错误的。它将为您提供计算机上指针的大小,因此从那时起,您使用
    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
    免费(空)
    是完全合法的


    @我当然是。你也是;如果你不相信我,试试看。
    void destructor(TOPOLOGY * top)
    {
        free(top->sizes);
        free(top->coords);
        free(top->name);
        free(top);
    }