结构

时间:2016-03-02 17:43:12

标签: c struct malloc

我的代码使用两种结构,块和布局(它是任意数量的块的集合)。

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()中的注释所标记的那样。 我的实施中会错过什么?

2 个答案:

答案 0 :(得分:1)

当你为任何东西分配内存时,你需要仔细分析 - &#34; 我为什么分配内存?&#34;

下面,您错误地假设任意数字block_no强制将充分调整new_layout.blocksnew_layout.moves所需的内存大小 - 它赢了&# 39; T:

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

您为new_layout.blocks分配的内容实际上是struct block *blocks;的空间(指针到结构块),而您可以malloc (block_no * sizeof (struct block));分配block_no struct block的空间,最好根据你创建的内容进行分配(即数组的空间new_layout.blocks(同样是指向结构块的指针 )需要block_no * sizeof *new_layout.blocks字节的内存来保存block_no类型的struct 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个短裤,所以你需要两次取消引用指针到指针到短路两次以分配给{ {1}})

另请参阅: Do I cast the result of malloc?以获得详尽的解释。

答案 1 :(得分: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仅出现一次。

: - )