簡體   English   中英

在c中為結構動態分配內存

[英]Dynamic memory allocation for structs in c

我正在嘗試通過向其分配內存以及使用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;
}

但是,當我這樣做時,它將內存分配給該結構,而不分配給它的任何成員指針(它們只是指向垃圾)。

我究竟做錯了什么? 謝謝

正如解釋在這里malloc不“干凈”的記憶,那則可以滿是垃圾(例如因為相同的內存是由另一個調用返回malloc()使用,然后free() 三種經典解決方案是:

  • 忍受它。 在使用struct之前,先手動設置struct所有成員(如果使用malloc分配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中,您不需要/也不應該calloc malloc / calloc返回的指針( 但是實際上,如果您使用的是C ++編譯器,則必須強制轉換... )。

如果要清除內存(而不是其中包含垃圾的內存),則需要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 ++向量構造函數。)

結構

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

有兩個指針作為成員。 因此,在32位OS上, sizeof(name_t)為8個字節。 動態創建name_t結構實例

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

僅分配8個字節來存儲兩個指針。 正如xanatos所說,分配的內存是垃圾,指針將指向隨機位置。 您可以在分配name_dict時使用calloc()或將其手動無效化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));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM