#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 分配内存并初始化多层嵌套结构体
struct Outer* createOuter() {
struct Outer* outer = (struct Outer*)malloc(sizeof(struct Outer));
if (outer == NULL) {
perror("malloc outer");
return NULL;
}
outer->value = 0.0;
for (int i = 0; i < 5; i++) {
outer->innerArr[i] = (struct Inner*)malloc(sizeof(struct Inner));
if (outer->innerArr[i] == NULL) {
perror("malloc inner");
// 释放已分配的内存
for (int j = 0; j < i; j++) {
free(outer->innerArr[j]);
}
free(outer);
return NULL;
}
outer->innerArr[i]->str = (char*)malloc(10 * sizeof(char));
if (outer->innerArr[i]->str == NULL) {
perror("malloc inner str");
// 释放已分配的内存
for (int j = 0; j < i; j++) {
free(outer->innerArr[j]->str);
free(outer->innerArr[j]);
}
free(outer);
return NULL;
}
strcpy(outer->innerArr[i]->str, "default");
outer->innerArr[i]->num = 1;
}
return outer;
}
// 将Outer结构体中所有Inner结构体的num值翻倍
void doubleInnerNums(struct Outer* outer) {
for (int i = 0; i < 5; i++) {
outer->innerArr[i]->num *= 2;
}
}
// 释放该结构体所有分配内存
void freeOuter(struct Outer* outer) {
for (int i = 0; i < 5; i++) {
free(outer->innerArr[i]->str);
free(outer->innerArr[i]);
}
free(outer);
}
int main() {
struct Outer* outer = createOuter();
if (outer != NULL) {
doubleInnerNums(outer);
for (int i = 0; i < 5; i++) {
printf("Inner %d: str = %s, num = %d\n", i, outer->innerArr[i]->str, outer->innerArr[i]->num);
}
freeOuter(outer);
}
return 0;
}
常见问题及避免方法
- 内存泄漏:
- 问题:在分配内存后,如果后续操作失败,没有释放已经分配的内存,就会导致内存泄漏。例如,在分配
Inner
结构体数组元素或str
字符串内存失败时,没有释放之前已分配的Outer
结构体或Inner
结构体。
- 避免方法:在每次分配内存后,立即检查返回值是否为
NULL
。如果分配失败,按照正确的顺序释放之前已经分配的所有内存。
- 悬空指针:
- 问题:当释放了一块内存,但没有将指向该内存的指针设置为
NULL
时,该指针就成为悬空指针。如果后续不小心使用了这个悬空指针,可能会导致程序崩溃。
- 避免方法:在释放内存后,立即将指针设置为
NULL
。例如,在freeOuter
函数中释放Outer
结构体后,虽然这里没有后续使用指针的情况,但良好的习惯是将传入的指针参数设置为NULL
。
- 双重释放:
- 问题:对同一块内存进行多次释放会导致未定义行为。通常是由于逻辑错误,在代码的不同地方重复释放了同一块内存。
- 避免方法:仔细设计内存管理逻辑,确保每块内存只被释放一次。可以通过设置标志位或者在释放内存后将指针置
NULL
,这样在尝试再次释放时可以通过判断指针是否为NULL
来避免双重释放。