关注struct指针

时间:2012-09-12 14:41:39

标签: c pointers struct

我正在做一个项目,我们的教授给我们的代码包含我们无法改变的变量和原型声明。一个是结构体,指向该结构的指针的类型定义为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)。根据我的理解,我没有为那个新指针分配空间,但每次它都没有任何问题。我可以很好地访问新结构的成员,我没有得到堆损坏错误或访问冲突或类似的东西。我的担忧是正确还是我怀疑自己?

3 个答案:

答案 0 :(得分:3)

根据您显示的代码,您的疑虑是有效的。

这一行:

g_ppRecords = (pStudentRecord*)  malloc(sizeof(pStudentRecord));

仅为 pStudentRecord分配足够的空间。可以将此视为pStudentRecord的数组,只有一个元素,位于g_ppRecords[0]

  

如果我添加更多记录,那么将在g_ppRecords的下一个位置创建一个新指针(pStudentRecord)。

现在问题是当你做你在这里描述的事情时会发生什么。添加新指针时会发生什么?除非您使用reallocg_ppRecords获得更多空间,否则 在该数组中有足够的空间来获取更多指向记录的内容。如果malloc在第二个元素处有一个新指针,即:

g_ppRecords[1] = (pStudentRecord) malloc(16);

然后您使用的内存g_ppRecords[1]已分配尚未。这可能出现,但这个记忆不属于您。继续添加新指针,最终你的程序将会中断。或者你的程序可能因代码的另一部分完全不相关而破坏。

修复是你应该最初分配你的数组,以便它可以容纳多个指针,而不是只有一个。如何使用第一个malloc行完成此操作?

我应该补充一点,当您使用structmalloc(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));
}

我在没有编译和测试的情况下编写了所有这些内容,因此可能存在错误(但不是我的作业:-))