#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义内层结构体
typedef struct Inner {
char *str;
} Inner;
// 定义外层结构体
typedef struct Outer {
Inner *innerArray;
} Outer;
// 分配内存函数
void allocateMemory(Outer *outer, int size) {
outer->innerArray = (Inner *)malloc(size * sizeof(Inner));
if (outer->innerArray == NULL) {
fprintf(stderr, "内存分配失败\n");
return;
}
for (int i = 0; i < size; i++) {
outer->innerArray[i].str = (char *)malloc(100 * sizeof(char));
if (outer->innerArray[i].str == NULL) {
// 释放之前分配的内存
for (int j = 0; j < i; j++) {
free(outer->innerArray[j].str);
}
free(outer->innerArray);
fprintf(stderr, "内存分配失败\n");
return;
}
strcpy(outer->innerArray[i].str, "示例字符串");
}
}
// 释放内存函数
void freeMemory(Outer *outer, int size) {
for (int i = 0; i < size; i++) {
free(outer->innerArray[i].str);
}
free(outer->innerArray);
}
int main() {
Outer outer;
int size = 5;
allocateMemory(&outer, size);
// 使用结构体数据
freeMemory(&outer, size);
return 0;
}
多层动态分配结构体内存过程中可能出现的错误点:
- 内存分配失败:在调用
malloc
时可能由于系统内存不足等原因导致分配失败,如 outer->innerArray = (Inner *)malloc(size * sizeof(Inner));
和 outer->innerArray[i].str = (char *)malloc(100 * sizeof(char));
这两步分配操作。如果不检查返回值,后续使用未成功分配的指针会导致程序崩溃。
- 内存泄漏:如果在分配内层结构体数组元素的字符数组时失败,而之前已经分配了内层结构体数组,没有及时释放内层结构体数组的内存,就会造成内存泄漏。例如上述代码中如果
outer->innerArray[i].str
分配失败,而没有释放之前 outer->innerArray
已分配的内存。
- 悬空指针:当释放了内存,但没有将指针设置为
NULL
时,指针仍然指向已释放的内存区域,成为悬空指针。后续如果误使用该指针,可能导致未定义行为。
优化错误检测机制避免内存泄漏和悬空指针等问题的方法:
- 检查内存分配结果:每次调用
malloc
后,立即检查返回值是否为 NULL
,如上述代码中所做的,若为 NULL
则及时处理,比如释放之前已分配的内存并给出错误提示。
- 按顺序释放内存:释放内存时,按照分配的相反顺序进行。先释放内层结构体中的动态分配内存(如字符数组),再释放外层结构体中指向内层结构体数组的指针。
- 置空指针:在释放内存后,将指针设置为
NULL
。例如在 freeMemory
函数中,释放完 outer->innerArray
后,可添加 outer->innerArray = NULL;
,这样可以避免悬空指针问题。