我正在做一个项目,我们的教授给我们的代码包含我们无法改变的变量和原型声明。一个是结构体,指向该结构的指针的类型定义为pStudentRecord
:
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
}* pStudentRecord;
使用指向此类型的指针g_ppRecords
。这将是一个动态的指向上面结构的指针数组。
这是我的问题所在。记录将从文件中读取。如果指定的文件名不存在,则创建一个新文件名。每当用户添加第一个新记录时,我正在初始化g_ppRecords
指针:
if(!n) //where n = number of records
g_ppRecords = (pStudentRecord*) malloc(sizeof(pStudentRecord));
g_ppRecords[n] = (pStudentRecord) malloc(16);
到目前为止,每次运行此代码都有效,但我不确定如何。如果我添加更多记录,那么将在pStudentRecord
的下一个位置创建一个新指针(g_ppRecords
)。根据我的理解,我没有为那个新指针分配空间,但每次它都没有任何问题。我可以很好地访问新结构的成员,我没有得到堆损坏错误或访问冲突或类似的东西。我的担忧是正确还是我怀疑自己?
答案 0 :(得分:3)
根据您显示的代码,您的疑虑是有效的。
这一行:
g_ppRecords = (pStudentRecord*) malloc(sizeof(pStudentRecord));
仅为单 pStudentRecord
分配足够的空间。可以将此视为pStudentRecord
的数组,只有一个元素,位于g_ppRecords[0]
。
如果我添加更多记录,那么将在
g_ppRecords
的下一个位置创建一个新指针(pStudentRecord)。
现在问题是当你做你在这里描述的事情时会发生什么。添加新指针时会发生什么?除非您使用realloc
为g_ppRecords
获得更多空间,否则 在该数组中有足够的空间来获取更多指向记录的内容。如果malloc
在第二个元素处有一个新指针,即:
g_ppRecords[1] = (pStudentRecord) malloc(16);
然后您使用的内存g_ppRecords[1]
已分配尚未。这可能出现,但这个记忆不属于您。继续添加新指针,最终你的程序将会中断。或者你的程序可能因代码的另一部分完全不相关而破坏。
修复是你应该最初分配你的数组,以便它可以容纳多个指针,而不是只有一个。如何使用第一个malloc
行完成此操作?
我应该补充一点,当您使用struct
为malloc(16)
分配内存时,您需要对您不应该做的数据结构做出假设,特别是{{1}将始终占用16个字节。鉴于您的struct
:直接指向来自匿名typedef
的指针,您可以将struct
更改为更一般的内容,但这与您的问题没有直接关系,并且你应该向教授询问的事情。
答案 1 :(得分:1)
作为一般规则,请尽量避免使用malloc( sizeof( type ))
,尤其是当类型被类型转换混淆时。在变量malloc( sizeof x )
上调用sizeof会更安全。此外,在C中,您不应该从malloc转换返回。换句话说,不是仅为一条记录分配空间:
g_ppRecords = (pStudentRecord*) malloc(sizeof(pStudentRecord));
通过编写以下内容为n条记录分配空间会更好:
g_ppRecords = malloc( n * sizeof *g_ppRecords );
答案 2 :(得分:0)
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
}* pStudentRecord;
这是一个匿名结构。这里有点奇怪,但也许教给你一些东西。这样做是为了创建一个新的:
pStudentRecord ptr;
ptr = malloc(sizeof(*ptr));
这将自动malloc适当的内存量。
你仍然遇到问题,因为你需要malloc数组来保存指针。为此:
pStudentRecord* g_ppRecords = malloc(n * sizeof(pStudentRecord));
然后您可以像这样使用g_ppRecords:
pStudentRecord ptr = g_ppRecords[3];
总而言之,我们有自定义分配器:
pStudentRecord* g_ppRecords = malloc(n * sizeof(pStudentRecord));
for (size_t i = 0; i < n; ++i)
{
pStudentRecord ptr;
g_ppRecords[i] = malloc(sizeof(*ptr));
}
我在没有编译和测试的情况下编写了所有这些内容,因此可能存在错误(但不是我的作业:-))