c中结构的动态内存分配

时间:2018-05-23 13:10:17

标签: c pointers dynamic struct malloc

我试图通过为它分配内存来初始化一个结构,并使用malloc指向它们的指针成员:

typedef struct {
    char *name;
    prob_t *prob;
} name_t;

我知道一旦初始化结构,我需要分别为指针分配内存:

name_t
*init_name_dict() {
    name_t *name_dict;
    name_dict = (name_t*)malloc(MAX_LINES*sizeof(*name_dict));
    name_dict->name = (char*)malloc(MAX_LEN*sizeof(*name_dict->name));
    name_dict->prob = (prob_t*)malloc(MAX_PROB*sizeof(*name_dict->prob));
    return name_dict;
}

但是当我这样做时,它会为结构分配内存,但不会为其任何成员指针分配内存(它们只指向垃圾)。

我做错了什么?感谢

3 个答案:

答案 0 :(得分:4)

正如here所解释的那样,malloc不会“清理”内存,然后就会充满垃圾(因为例如,另一次调用malloc()会返回相同的内存,使用然后free())。三种经典的解决方案是:

  • 和它一起生活。手动设置struct的所有成员(如果是的话) 在使用malloc之前使用struct分配struct(或者通常将获得的所有内存设置为您想要的值)
  • 在使用之前使用memset将所有内存归零
  • 使用calloc代替malloc(请注意,它的签名略有不同)。 callocmalloc + memset类似。举个例子:

name_t *init_name_dict() {
    name_t *name_dict;
    name_dict = calloc(MAX_LINES, sizeof(*name_dict));
    name_dict->name = calloc(MAX_LEN, sizeof(*name_dict->name));
    name_dict->prob = calloc(MAX_PROB, sizeof(*name_dict->prob));
    return name_dict;
}

作为旁注,在C中你不需要/不应该转换malloc / callocbut if in truth you are using a C++ compiler then you have to cast it...)返回的指针。

答案 1 :(得分:1)

如果你想要清除内存(而不是带有垃圾的内存),你需要calloc 而不是malloc,但这是微不足道的。

你有更大的问题:

1) no error checking
2) possibly needless malloc calls
3) you're allocating MAX_LINES of theses name_t structure but initializing 
  only one of them

如果不会重新分配.name.prob字段,则应更改name_t

的定义
typedef struct { char name[MAX_LEN]; prob_t prob[MAX_PROB]; } name_t;

并一次性分配所有MAX_LINES name_t:calloc(MAX_LINES, sizeof(name_t))

如果你需要原始的name_t结构,那么我就有一个初始化器:

int init_name_dict (name_t  *this)
{
    if(0==(this->name=calloc(MAX_LEN, sizeof *this->name))) return -1;
    if(0==(this->prob=calloc(MAX_PROB, sizeof *this->prob))){ free(this->name); return -1; }
    return 0;
}

它的析构函数

void destroy_name_dict(name_t *this) { free(this->name); free(this->prob); }

然后是整个数组的初始化分配器:

name_t* new_name_dicts(void)
{
    name_t *r = malloc(MAX_LINES*sizeof *r);
    if(!r) return r;
    int i;
    for(i=0; i<MAX_LINES; i++)
        if(0>init_name_dict(&r[i])) goto fail;
    return r;
    fail:
        for(--i; i>=0; --i)
            destructor_name_dict(&r[i]);
    return NULL;
}

(基本上是一个C ++向量构造函数,它可以获取构造函数  细胞类型。)

答案 2 :(得分:-1)

结构

typedef struct {
    char *name;
    prob_t *prob;
} name_t;

有两个指针作为成员。因此,在32位OS上,sizeof(name_t)是8个字节。 动态创建name_t struct

的实例
name_t *name_dict = (name_t*)malloc(sizeof(name_dict));

仅分配8个字节来存储两个指针。正如xanatos所说,分配的内存是垃圾,指针会指向随机位置。您可以在分配calloc()时使用name_dict,也可以手动使其name_dict->name = NULL;name_dict->prob = NULL;无效。你也可以不用指针的内容来打扰自己,并在下一个代码行中为成员分配内存

name_dict->name = (char*)malloc(MAX_LEN*sizeof(char));
name_dict->prob = (prob_t*)malloc(sizeof(prob_t));

您还可以检查内存是否分配好,两个指针都不指向NULL。

总结一下,正确编写了init_name_dict()方法

name_t * init_name_dict() 
{
  name_t *name_dict = (name_t*)malloc(sizeof(name_t));
  if  (name_dict != NULL)
  {
        name_dict->name = (char*)malloc(MAX_LEN*sizeof(char)));
        name_dict->prob = (prob_t*)malloc(sizeof(prob_t));
  }
  return name_dict;
 }
代码中的

错误

  • 这里有MAX_LINES(假设你想在这里只创建一个结构)

    name_dict = (name_t*)malloc(MAX_LINES*sizeof(*name_dict));

  • MAX_PROB(假设您只想创建一个结构) 这里)

    name_dict->prob = (prob_t*)malloc(MAX_PROB*sizeof(*name_dict->prob));