C中的指针无效

时间:2013-11-17 04:32:18

标签: c struct

我提前道歉,但这有点长。

在我的程序中,我读了学生的信息,但是当我输出它时,它会出现乱码,然后出现指针错误。

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

struct student{
        char *firstName;
        char *lastName;
        char id[10];
        char gender;
        int age;
        double gpa;
};

void main()
{
    int n;
    struct student *classroom;

    printf("How many students?");
    scanf("%d",&n);
    classroom = (struct student*) malloc(n*sizeof(struct student));

    if (classroom == NULL)
    exit(1);

readStudentsInformation(classroom,n);
outputStudents(classroom,n);
printf("The average age is %.2f.\n",averageAge(classroom,n));
printf("The average GPA is %.2f.\n",averageGpa(classroom,n));
sortByLastName(classroom,n);
outputStudents(classroom,n);
sortByID(classroom,n);
outputStudents(classroom,n);
sortByAge(classroom,n);
}

void outputStudents(struct student classroom[], int size)
{

    int i;
    for (i = 0; i < size; i++)
    {
        printf("%15s",classroom[i].firstName);
        printf("%15s:",classroom[i].lastName);
        printf("%14s,",classroom[i].id);
        printf("%3c",classroom[i].gender);
        printf("%5d",classroom[i].age);
        printf("%5.2f",classroom[i].gpa);
    }
}

输入:    有多少学生?2    名字?汤姆    姓氏?Arron    ID?2    性别?m    年龄?26    GPA?3.9    名字?弗兰克    姓氏?罗伯茨    ID?1    性别?F的    年龄?24    GPA?3.4'

输出:

    Roberts        Roberts:             2,  M   26 3.90                              :             1,  F   24 3.40The average age is 25.00.

平均GPA为3.65。 检测到 * glibc * ./lab12:munmap_chunk():指针无效:0x00007fff30319a90 *

                       :             2,  M   26 3.90Aborted (core dumped)

完整的代码在这里,但我不想复制200行到堆栈溢出:http://codepad.org/LYpS6t5z

知道会导致什么原因吗?

3 个答案:

答案 0 :(得分:1)

这是一个概念上的错误,你可以在几个地方找到它

classroom[i].firstName = (char*)malloc(sizeof(char)*(1+strlen(temp)));
if (classroom[i].firstName == NULL)
     exit(1);
classroom[i].firstName = temp;

你想要的是

classroom[i].firstName = (char*)malloc(sizeof(char)*(1+strlen(temp)));
if (classroom[i].firstName == NULL)
     exit(1);
strcpy(classroom[i].firstName, temp); // note this

或者,清理了一下:

classroom[i].firstName = malloc(1+strlen(temp)); // note clean up here
if (classroom[i].firstName == NULL)
     exit(1);
strcpy(classroom[i].firstName, temp);

甚至只是

classroom[i].firstName = strdup(temp); // this takes place of all the lines above

这些错误解释了为什么你的免费失败。

没有别的事情发生在我身上。

答案 1 :(得分:1)

classroom[i].firstName = (char*)malloc(sizeof(char)*(1+strlen(temp)));
if (classroom[i].firstName == NULL)
    exit(1);
classroom[i].firstName = temp;

此处的第二个分配将覆盖地址,泄漏malloc内存,并在for迭代完成后立即使指针无效。 lastName重复使用相同的缓冲区(具有相同的错误),这就是为什么您会看到Roberts Roberts而不是实际的名字和姓氏。当你去free时,他们(1)无效,(2)不是malloc,所以你得到了你看到的崩溃。

就像其他数组一样,你不能通过赋值复制它们,你必须逐字节复制:

size_t len = strlen(temp);
classroom[i].firstName = malloc(1+len);
if (classroom[i].firstName == NULL)
    exit(1);
strncpy(classroom[i].firstname, temp, len);
classroom[i].firstname[len] = '\0';

不要投射malloc的结果。

答案 2 :(得分:1)

readStudentsInformation 中发生了奇怪,特别是像

这样的行

classroom[i].lastName = temp;

当您尝试使用

释放此内存时,

会导致问题

free(classroom[i].firstName);

下面适当的内存处理:

void readStudentsInformation(struct student classroom[], int size)
{
  int i;
  char temp[50];

  for (i = 0; i < size; i++)
  {
    printf("First Name?");
    scanf("%s",temp);
    classroom[i].firstName = (char*)malloc(sizeof(char)*(1+strlen(temp)));
    if (classroom[i].firstName == NULL)
      exit(1);
    /* after mallocing good memory can write in the data.. */
    strcpy(classroom[i].firstName, temp);
/*    classroom[i].firstName = temp; */
    printf("Last Name?");
    scanf("%s",temp);
    classroom[i].lastName = (char*)malloc(sizeof(char)*(1+strlen(temp)));
    if (classroom[i].lastName == NULL)
      exit(1);
/*    classroom[i].lastName = temp; */
    strcpy(classroom[i].lastName, temp);
    printf("ID?");
    scanf("%s",classroom[i].id);
    fflush(stdin);
    __fpurge(stdin);
    printf("Gender?");
    scanf("%c",&classroom[i].gender);
    printf("Age?");
    scanf("%d",&classroom[i].age);
    printf("GPA?");
    scanf("%lf",&classroom[i].gpa);
  }
}