C - 结构中的内存分配



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

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() 中的注释所示。我在实施中错过了什么?

当你为任何事情分配内存时,你需要仔细分析——"我分配内存是为了什么?

下面,您错误地假设任意数字的强制转换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分配的实际上是struct block *blocks;的空间(指针到结构块),虽然您可以malloc (block_no * sizeof (struct block));为结构块分配空间block_no但最好根据您正在创建的内容进行分配(即数组new_layout.blocks的空间(再次是指向结构块),需要 block_no * sizeof *new_layout.blocks 字节的内存来容纳 struct block 类型的block_no, 例如:

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)

另请参阅:我是否投射 malloc 的结果?以获得详尽的解释。

对于初学者来说,这个

  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只出现一次。

:-)

相关内容

  • 没有找到相关文章

最新更新