我的代码使用两种结构,块和布局(这是任意数量的块的集合)。
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.blocks
和new_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
只出现一次。
:-)