问题描述
如果你想分配一个结构体数组,你可以通过声明类似的东西来静态地完成
struct myStruct myStructArray[100];
或动态地使用类似的东西
struct myStruct *myStructArray = calloc(100,sizeof(struct myStruct) );
但在这种情况下,您负责释放内存。
在许多应用程序和示例中,我发现了一种混合方法:
struct wrapperStruct
{
int myInt;
struct myStruct myStructArray[1];
};
然后分配是这样进行的
int n = 100;
size_t memory_size = sizeof(struct wrapperStruct) + (n - 1) * sizeof(struct myStruct);
struct wrapperStruct *wrapperStruct_p = calloc(1,memory_size);
所以(如果我理解正确的话)因为数组是结构体的最后一个成员并且结构体的字段在内存中遵循相同的位置,那么您“扩展”了具有 99 个条目的单条目数组 myStructArray
.
这允许您安全地编写类似 wrapperStruct_p.myStructArray[44]
的内容,而不会导致缓冲区溢出,也无需创建动态分配的结构数组,然后在最后处理内存处理。所以替代方法是:
struct wrapperStruct
{
int myInt;
struct myStruct *myStructArray;
};
struct wrapperStruct *wrapperStruct_p = calloc(1,sizeof(struct wrapperStruct) );
wrapperStruct_p.myStructArray = calloc(100,sizeof(struct myStruct) )
问题是当您尝试释放 wrapperStruct_p
变量时会发生什么?
您是否导致内存泄漏?
C 内存管理是否能够理解结构数组由 100 个条目组成而不是 1 个条目?
除了不必释放结构体内部的指针外,第一种方法还有什么好处?
解决方法
问题是当你尝试释放 wrapperStruct_p 时会发生什么 变量?
您是否导致内存泄漏?
很有可能,但不是必需的。内部动态数组的内存没有被释放,但如果你将指针地址保存到其他变量,你仍然可以稍后释放它。
C 内存管理是否能够理解结构数组由 100 个条目组成而不是 1 个条目?
“C 内存管理”负责堆栈和堆分配(后者使用 systemcalls 所以也许它不是真正的“C 内存管理”),除了提供语法糖外,它没有做太多其他事情汇编程序的顶部(与 Java 或其他垃圾收集语言不同)。
C 本身并不关心某处有多少条目以及您访问的内存部分(SEGFAULTS 是操作系统对内存访问冲突的响应)
第一种方法除了不必这样做有什么好处 释放结构内的指针?
如果“第一种方法”是指堆栈分配的数组,那么主要是因为您不需要分配任何东西,堆栈会为您分配(缺点是它保持在声明的范围内分配,您可以' t 释放或增加数组空间)那么恒定的分配速度和保证无论操作系统响应如何,您都将获得 100 个数组项(许多实时应用程序需要最大响应时间,因此堆分配可能是一个非常大的减速,导致问题).
如果“第一种方法”是指使用包装器结构,那么除了您已经说明的好处之外,我看不到任何好处。
我什至建议你不要提倡/使用这种方法,因为它是一种非常令人困惑的技术,并没有带来明显的好处(而且它分配了 1 个空间,即使它甚至可能不被使用,但这是一个细节)
主要目标是编写其他人容易理解的代码。现在机器和编译器可以用代码创造奇迹,所以除非你是编译器设计者、标准库开发者或机器级程序员对于嵌入式系统,您应该编写简单易懂的代码。