C (std=c99) 指向结构内存分配的指针
C (std=c99) pointer to structs memory allocation
所以,这工作正常...这意味着,没有编译器错误,似乎没有内存泄漏,它正在做我想做的事。那说它应该工作吗?当我转到 books_init 时,我将一个局部变量发送到集合,这是否意味着当我返回到 main 时它不应该工作? (或未定义的行为?)。另外,如果你说我必须 malloc 它,我必须在之后释放它吗? (对清理发表评论)
/* pseudo struct Collection{
size_t size, capacity;
Volume *volumes;
} */
void collection_init(Collection *col, size_t capacity){
col->size = 0;
col->capacity = capacity;
col->volumes = malloc(sizeof(Volume) * capacity);
}
void collection_resize(Collection *col, size_t capacity){
Volume *v = realloc(col->volumes, capacity * sizeof(Volume));
if(!v) return;
col->capacity = capacity;
col->volumes = v;
}
void collection_add(Collection *col, Volume *volume){
if(col->size >= col->capacity)
collection_resize(col, col->capacity * 2);
col->volumes[col->size++] = *volume;
}
void collection_clean(Collection *col){
//for(vol : col->vol) free(vol);
//should I free every element or just volumes?
free(col->volumes);
}
void books_init(Collection *col){
for(int i = 0; i < 25; ++i){
Volume v = {.swag = i};
collection_add(col, &v);
}
}
int main(){
Collection col;
collection_init(&col, 10);
books_init(&col);
for(int i = 0; i < col.size; ++i){
printf("\tVol[%d].id = %d\n", i, col.volumes[i].swag);
}
collection_clean(&col);
return 0;
}
感谢您的宝贵时间
这一行在books_init
Volume v = {.swag = i};
创建一个名为 v
的局部变量,成员 swag
初始化为 i
。然后将该变量的地址传递给 collection_add
。这是允许的,因为 v
仍在范围内。
这一行在collection_add
col->volumes[col->size++] = *volume;
对 Volume
结构的内容进行 复制,并将该副本存储在 collection_init
中分配的内存中。
在collection_add
returns之后,books_init
中的变量v
超出范围,但是没关系,因为v
的内容被复制了保存在col->volumes
指向的内存中。
程序结束时,collection_clean
只需要
free(col->volumes);
从内存中删除所有 Volume
个副本。
我在您的程序中看到的唯一缺陷是 realloc
失败。在那种情况下,您仍然写入 Volume
数组。这将导致缓冲区溢出和内存损坏。为避免这种情况,collection_add
函数应在执行复制之前验证 collection_resize
函数是否成功。例如,您可以在复制之前再次检查 col->capacity > col->size
。
TL;DR 只要 realloc
始终成功,您的代码就没问题。
所以,这工作正常...这意味着,没有编译器错误,似乎没有内存泄漏,它正在做我想做的事。那说它应该工作吗?当我转到 books_init 时,我将一个局部变量发送到集合,这是否意味着当我返回到 main 时它不应该工作? (或未定义的行为?)。另外,如果你说我必须 malloc 它,我必须在之后释放它吗? (对清理发表评论)
/* pseudo struct Collection{
size_t size, capacity;
Volume *volumes;
} */
void collection_init(Collection *col, size_t capacity){
col->size = 0;
col->capacity = capacity;
col->volumes = malloc(sizeof(Volume) * capacity);
}
void collection_resize(Collection *col, size_t capacity){
Volume *v = realloc(col->volumes, capacity * sizeof(Volume));
if(!v) return;
col->capacity = capacity;
col->volumes = v;
}
void collection_add(Collection *col, Volume *volume){
if(col->size >= col->capacity)
collection_resize(col, col->capacity * 2);
col->volumes[col->size++] = *volume;
}
void collection_clean(Collection *col){
//for(vol : col->vol) free(vol);
//should I free every element or just volumes?
free(col->volumes);
}
void books_init(Collection *col){
for(int i = 0; i < 25; ++i){
Volume v = {.swag = i};
collection_add(col, &v);
}
}
int main(){
Collection col;
collection_init(&col, 10);
books_init(&col);
for(int i = 0; i < col.size; ++i){
printf("\tVol[%d].id = %d\n", i, col.volumes[i].swag);
}
collection_clean(&col);
return 0;
}
感谢您的宝贵时间
这一行在books_init
Volume v = {.swag = i};
创建一个名为 v
的局部变量,成员 swag
初始化为 i
。然后将该变量的地址传递给 collection_add
。这是允许的,因为 v
仍在范围内。
这一行在collection_add
col->volumes[col->size++] = *volume;
对 Volume
结构的内容进行 复制,并将该副本存储在 collection_init
中分配的内存中。
在collection_add
returns之后,books_init
中的变量v
超出范围,但是没关系,因为v
的内容被复制了保存在col->volumes
指向的内存中。
程序结束时,collection_clean
只需要
free(col->volumes);
从内存中删除所有 Volume
个副本。
我在您的程序中看到的唯一缺陷是 realloc
失败。在那种情况下,您仍然写入 Volume
数组。这将导致缓冲区溢出和内存损坏。为避免这种情况,collection_add
函数应在执行复制之前验证 collection_resize
函数是否成功。例如,您可以在复制之前再次检查 col->capacity > col->size
。
TL;DR 只要 realloc
始终成功,您的代码就没问题。