释放结构数组的内存
Freeing memory of struct array
我有两个结构:
struct product {
char *title; // Name of the product
char code[8]; // Max. 7 characters of product ID
int stock; // Current stock (number of units)
double price; // Price of a single unit
};
struct product_array {
struct product *arr;
unsigned int count;
};
我正在使用功能将产品添加到 product_array:
void add_product(struct product_array *pa, const char *title, const char *code,
int stock, double price) {
pa->count++;
struct product* nProduct = malloc(sizeof (struct product));
if (!nProduct) free(nProduct);
init_product(nProduct, title, code, stock, price);
pa->arr = realloc(pa->arr, (pa->count) * sizeof (struct product));
if (!pa->arr) free(pa->arr);
pa->arr[pa->count - 1] = *nProduct;
}
void init_product(struct product *pr, const char *title, const char *code,
int stock, double price) {
int titleLen = strlen(title);
int codeLen = strlen(code);
char *aTitle = calloc((1 + titleLen) * sizeof (char), 1);
strncpy(aTitle, title, titleLen);
char* codePtr = strncpy(pr->code, code, codeLen);
if (codeLen <= 7)
*(codePtr + codeLen) = 0;
else
*(codePtr + 7) = 0;
pr->title = aTitle;
pr->stock = stock;
pr->price = price;
}
add_product 在 main.c
中是这样工作的
struct product_array pa;
pa.count = 0;
pa.arr = NULL;
struct product p;
init_product(&p, "test", "0000", 1, 0.50);
print_products(&pa);
add_product(&pa, "Product 1", "0000", 0, 10);
add_product(&pa, "Long name, isn't it", "1234567890", 10, 100);
add_product(&pa, "Product 3", "9999999", 0, 20);
print_products(&pa);
remove_all(&pa);
当我试图释放所有分配的内存时,我 运行 遇到了问题。这是删除所有功能:
int remove_all(struct product_array *pa) {
unsigned int i;
unsigned int until = pa->count;
struct product *prdPtr = pa->arr;
struct product *next;
for (i = 0; i < until; i++) {
next = prdPtr + 1;
free(prdPtr->title);
free(prdPtr); // this raises error
prdPtr = next;
}
if (pa->arr != NULL) {
free(pa->arr);
}
pa->count = 0;
return 1;
}
for-loop 溢出,但我现在正试图找出在此上下文中释放内存的逻辑。
在 remove_all 函数中,我想释放 product_array 的所有内存。我正在遍历数组中的每个(结构)产品并释放标题的内存。释放标题记忆后,我试图释放结构产品本身。它在第一次迭代中工作,但是当我进入第二个元素时,标题可以被释放但是 free(prdPtr) 引发了 SIGABRT。
我可能遗漏了什么?为什么我可以释放产品的标题而不是产品本身?
预先感谢您的帮助。
您两次释放同一个内存块:
// this makes pdrPtr to an alias of pa->arr
struct product *prdPtr = pa->arr;
for (i = 0; i < until; i++) {
...
free(prdPtr); // free prdPtr a.k.a. pa->arr
...
}
// here you free the same oject again.
free(pa->arr);
删除最后一个free(pa->arr);
。
pa->arr
是 struct product *
而不是 struct product **
。
所以你已经为 pa->arr
分配了内存,你应该只释放它一次。 pa->arr[i]
不是指针,只是一个结构体。
你不应该释放它,但你应该释放分配给它的成员的任何内存,比如 title
。
因此将您的 for 循环更新为
...
for (i = 0; i < until; i++) {
next = prdPtr + 1;
free(prdPtr->title); //just free members
prdPtr = next;
}
if (pa->arr != NULL) {
free(pa->arr);
}
...
编辑:
另请注意,add_product中有一个不必要的malloc
。建议修复:
void add_product(struct product_array *pa, const char *title, const char *code,
int stock, double price) {
struct product *pa_tmp;
pa->count++;
pa_tmp = realloc(pa->arr, (pa->count) * sizeof (struct product));
if (pa_tmp == null) {
/* handle out of memory error */
}
pa->arr = pa_tmp;
init_product(&pa->arr[pa->count - 1], title, code, stock, price);
}
我有两个结构:
struct product {
char *title; // Name of the product
char code[8]; // Max. 7 characters of product ID
int stock; // Current stock (number of units)
double price; // Price of a single unit
};
struct product_array {
struct product *arr;
unsigned int count;
};
我正在使用功能将产品添加到 product_array:
void add_product(struct product_array *pa, const char *title, const char *code,
int stock, double price) {
pa->count++;
struct product* nProduct = malloc(sizeof (struct product));
if (!nProduct) free(nProduct);
init_product(nProduct, title, code, stock, price);
pa->arr = realloc(pa->arr, (pa->count) * sizeof (struct product));
if (!pa->arr) free(pa->arr);
pa->arr[pa->count - 1] = *nProduct;
}
void init_product(struct product *pr, const char *title, const char *code,
int stock, double price) {
int titleLen = strlen(title);
int codeLen = strlen(code);
char *aTitle = calloc((1 + titleLen) * sizeof (char), 1);
strncpy(aTitle, title, titleLen);
char* codePtr = strncpy(pr->code, code, codeLen);
if (codeLen <= 7)
*(codePtr + codeLen) = 0;
else
*(codePtr + 7) = 0;
pr->title = aTitle;
pr->stock = stock;
pr->price = price;
}
add_product 在 main.c
中是这样工作的struct product_array pa;
pa.count = 0;
pa.arr = NULL;
struct product p;
init_product(&p, "test", "0000", 1, 0.50);
print_products(&pa);
add_product(&pa, "Product 1", "0000", 0, 10);
add_product(&pa, "Long name, isn't it", "1234567890", 10, 100);
add_product(&pa, "Product 3", "9999999", 0, 20);
print_products(&pa);
remove_all(&pa);
当我试图释放所有分配的内存时,我 运行 遇到了问题。这是删除所有功能:
int remove_all(struct product_array *pa) {
unsigned int i;
unsigned int until = pa->count;
struct product *prdPtr = pa->arr;
struct product *next;
for (i = 0; i < until; i++) {
next = prdPtr + 1;
free(prdPtr->title);
free(prdPtr); // this raises error
prdPtr = next;
}
if (pa->arr != NULL) {
free(pa->arr);
}
pa->count = 0;
return 1;
}
for-loop 溢出,但我现在正试图找出在此上下文中释放内存的逻辑。 在 remove_all 函数中,我想释放 product_array 的所有内存。我正在遍历数组中的每个(结构)产品并释放标题的内存。释放标题记忆后,我试图释放结构产品本身。它在第一次迭代中工作,但是当我进入第二个元素时,标题可以被释放但是 free(prdPtr) 引发了 SIGABRT。
我可能遗漏了什么?为什么我可以释放产品的标题而不是产品本身? 预先感谢您的帮助。
您两次释放同一个内存块:
// this makes pdrPtr to an alias of pa->arr
struct product *prdPtr = pa->arr;
for (i = 0; i < until; i++) {
...
free(prdPtr); // free prdPtr a.k.a. pa->arr
...
}
// here you free the same oject again.
free(pa->arr);
删除最后一个free(pa->arr);
。
pa->arr
是 struct product *
而不是 struct product **
。
所以你已经为 pa->arr
分配了内存,你应该只释放它一次。 pa->arr[i]
不是指针,只是一个结构体。
你不应该释放它,但你应该释放分配给它的成员的任何内存,比如 title
。
因此将您的 for 循环更新为
...
for (i = 0; i < until; i++) {
next = prdPtr + 1;
free(prdPtr->title); //just free members
prdPtr = next;
}
if (pa->arr != NULL) {
free(pa->arr);
}
...
编辑:
另请注意,add_product中有一个不必要的malloc
。建议修复:
void add_product(struct product_array *pa, const char *title, const char *code,
int stock, double price) {
struct product *pa_tmp;
pa->count++;
pa_tmp = realloc(pa->arr, (pa->count) * sizeof (struct product));
if (pa_tmp == null) {
/* handle out of memory error */
}
pa->arr = pa_tmp;
init_product(&pa->arr[pa->count - 1], title, code, stock, price);
}