【问题标题】:C - Output contains null values and segmentation faultC - 输出包含空值和分段错误
【发布时间】:2017-07-30 14:03:56
【问题描述】:

这个程序应该从代码开头的硬编码名称和年龄数组中创建一个包含名称和年龄值的结构体数组。 我被明确要求在主函数中声明数组,然后在插入函数中为其分配内存。该程序编译良好,我应该得到的输出是:

姓名:西蒙

年龄:22

姓名:苏西

年龄:24

姓名:阿尔弗雷德

年龄:106

名称:芯片

年龄:6

等等。等等

但是我得到的输出是这样的:

姓名:西蒙

年龄:22

名称:(空)

年龄:33

姓名:苏西

年龄:24

名称:(空)

年龄:33

姓名:苏西

年龄:24

..... 分段错误。

有的名字出现两次,有的名字为空,输出末尾有段错误。 任何帮助将不胜感激。非常感谢。

    #include <stdio.h>
    #include <stdlib.h>

    /* these arrays are just used to give the parameters to 'insert',
       to create the 'people' array 
    */

    #define HOW_MANY 7
    char *names[HOW_MANY]= {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim",
                  "Harriet"};
    int ages[HOW_MANY]= {22, 24, 106, 6, 18, 32, 24};

    /* declare your struct for a person here */
    struct person {
      char *name;
      int age;
    };

    static void insert(struct person **arr, char *name, int age) 
    {
      //initialise nextfreeplace
      static int nextfreeplace = 0;
      //allocate memory
      arr[nextfreeplace] = malloc (sizeof(struct person));
      /* put name and age into the next free place in the array parameter here */
      arr[nextfreeplace]->name = name;
      arr[nextfreeplace]->age = age;
      /* modify nextfreeplace here */
      nextfreeplace++;
    }

    int main(int argc, char **argv) 
    {

      /* declare the people array here */
      struct person *people;

      for (int i = 0; i < HOW_MANY; i++) 
      {
        insert (&people, names[i], ages[i]);
      }

      /* print the people array here*/
      for (int i = 0; i < HOW_MANY; i++)
      {
        printf("Name: %s \t Age: %i \n", people[i].name, people[i].age);
      }

      return 0;
    }

【问题讨论】:

  • 请勿发布代码图片,请发布代码本身。
  • 试试struct person *people; -> struct person *people[HOW_MANY];
  • @Annabelle:不,这是 C 而不是 C++。
  • @Marian: ... 并将insert(&amp;people, ... 更改为insert(people, ...
  • @Annabelle:您链接的问题只是带有错误的标签,即 C 标签,该标签也是后来才添加的,显然没有仔细阅读问题。在 C 中,struct 类型 always 需要携带 struct。这在 C++ 中是不同的。

标签: c pointers struct malloc


【解决方案1】:

在您的代码中,您有

#define HOW_MANY 7
/* ... */
struct person {
    /* ... */
};

static void insert(struct person **arr/* ... */) {
    static int nextfreeplace = 0;
    /* ... */
    arr[nextfreeplace] = malloc(sizeof(struct person));
    /* ... */
    nextfreeplace++;
}

int main(int argc, char **argv) {
    /* ... */
    struct person *people;

    for (int i = 0; i < HOW_MANY; i++) {
        insert(&people/* ... */);
    }
    /* ... */
    return 0;
}

问题是您将一个名为people 的变量定义为一个指针。然后将该指针的地址传递给insert。由于局部变量(通常)是在堆栈上分配的,因此您在 insert 中所做的分配会覆盖其中的一部分。

假设你有

struct person *people;
struct person *otherpeople;

然后,当您有nextfreeplace == 0 时,您分配给arr[0] == *arr,这很好。但是对于nextfreeplace == 1,您分配给arr[1] == *(arr+1) == otherpeople

这种类型的错误称为缓冲区溢出。

要修复此错误,您需要使用struct person *people[HOW_MANY];insert(people/* ... */);

附带说明:您还应该使用 free 释放已分配且不再需要的内存。

【讨论】:

  • 您好。感谢您抽出时间来提供帮助。该代码是我的 uni 课程的一部分,他们说“修改 insert 以调用 malloc 以创建一个新结构并设置指向它的正确数组元素。”我认为这意味着我不能只在主函数中使用 people[HOW_MANY] 来分配内存:(
  • 从“[...] 并设置正确的指向它的数组元素”,我假设您实际上应该使用指针数组然后分配内存中的每个指针。否则,您将需要为person 类型的HOW_MANY 结构分配内存(即struct person *people = malloc(HOW_MANY*sizeof(*people));),然后填充它们中的每一个。但是,你不会设置指针,分配将在insert之外。
猜你喜欢
  • 2019-03-07
  • 2023-03-03
  • 1970-01-01
  • 2013-06-23
  • 2013-12-17
  • 1970-01-01
  • 1970-01-01
  • 2021-04-22
相关资源
最近更新 更多