2016-03-02 104 views
0

我的代碼使用兩個結構,塊和佈局(這是一個任意數量的塊的集合)。結構中的內存分配

struct block{ 
    char type; 
    unsigned short int loc; 
    unsigned short int size[2]; 
}; 
struct layout{ 
    unsigned short int no; 
    struct block *blocks; 
    short int **moves; 
}; 

我使用這個功能來快速初始化(和部分填充)的結構佈局,基於一組塊:

struct layout init_layout(int block_no, struct block *blocks){ 
    struct layout new_layout; 
    int i, j; 

    new_layout.no = (unsigned short int)block_no; 
    // the following two lines cause an memory corruption error 
    new_layout.blocks = (struct block *)malloc(block_no); 
    new_layout.moves = (short int **)malloc(block_no); 
    for(i = 0; i < block_no; i++){ 
     new_layout.blocks[i] = blocks[i]; 
     new_layout.moves[i] = (short int *)malloc(2); 
     for(j = 0; j < 2; j++) 
      new_layout.moves[i][j] = 0; 
    } 

    return new_layout; 
} 

到目前爲止,我沒有看到,有一些錯誤用它。然而,當我打電話這樣的功能

int main(int argc, char** argv){ 
    // just some arbitrary values for 10 blocks 
    int size[2] = {2, 2}; 
    struct block *blocks = (struct block *)malloc(10); 
    for(length = 0; length < 10; length++){ 
     blocks[length] = init_block('R', 1, size); 
    } 

    struct layout puzzle; 
    puzzle = init_layout(10, blocks); 
    return 0; 
} 

我最終以內存損壞錯誤,由init_layout()中的評論標記。 我在執行中錯過了什麼?

+0

如果your'r最多使用2D陣列,用於'moves',最好使用一個,而不是一個指針的指針。 – Olaf

+0

那麼爲什麼不將'moves'的第0維移動到'block'? – user3528438

回答

1

當你分配的任何東西內存,你需要分析,密切 - 「它是什麼,我分配內存爲?」

下面,你會錯誤地假定的一個任意數量block_no將充分尺寸需要兩個new_layout.blocksnew_layout.moves記憶 - 它不會:

new_layout.blocks = (struct block *)malloc(block_no); 
new_layout.moves = (short int **)malloc(block_no); 

你所分配的new_layout.blocks實際上是空間(一個指針結構塊),而你可以malloc (block_no * sizeof (struct block));block_no結構塊分配空間,根據你正在創建的內容分配空間要好得多。用於陣列new_layout.blocks空間(再次指針到結構塊),其需要block_no * sizeof *new_layout.blocks字節的存儲器以保持block_nostruct block的類型,例如:

new_layout.blocks = malloc(sizeof *new_layout.blocks * block_no); 
new_layout.moves = malloc(sizeof *new_layout.moves * block_no); 

(簡單地解除引用所述對象您正在分配的陣列的,將精確允許您使用sizeof以獲取數組對象(元素)大小(例如sizeof *new_layout.blocks),你將你需要多少乘以(如sizeof *new_layout.blocks * block_no)

這同樣適用於:

new_layout.moves[i] = malloc(**new_layout.moves * 2); 

注:現在你在這裏分配2個短褲,所以你需要取消引用您指針到指針到短兩次被分配爲sizeof (short)

另請參見:Do I cast the result of malloc?以作詳細說明。

+0

也在主要的同一個問題:malloc(10 * sizeof(struct block)) – lowtech

+0

你應該詳細說明一點。只是提供一些代碼遲早會導致關於類似問題的問題。 – Olaf

+1

你丟掉了'block_no'。 – alk

1

對於初學者來說,這

new_layout.blocks = (struct block *)malloc(block_no); 

應該

new_layout.blocks = malloc(block_no * sizeof *new_layout.blocks); 

對於moves這是一個比較複雜一點。

假設short int **moves;應該引用的int[2]聲明某個號碼是不是最佳的,更好的應該是:

short int (*moves)[2]; /* Define a pointer to 
           an array with two elements of type short int. */ 

然後分配應該是這樣的:

new_layout.moves = malloc(block_no * sizeof *new_layout.moves); 

最後初始化是這樣的:

for(i = 0; i < block_no; i++){ 
    new_layout.blocks[i] = blocks[i]; 
    for(j = 0; j < sizeof new_layout.moves[0]/sizeof new_layout.moves[0][0]; j++) 
     new_layout.moves[i][j] = 0; 
    } 

您可能已經注意到:

  • 循環中沒有內存分配了。
  • 幻數2只出現一次。

:-)