Valgrind内存泄漏与动态数组和结构C

问题描述:

我有我的代码问题。代码编译并运行时没有警告或错误,这是我想要的,但Valgrind发现我无法修复的内存泄漏。我无法自己修改代码几天。你能指出我做错了吗?Valgrind内存泄漏与动态数组和结构C

这是练习,source.c是我自己编写的代码,其他所有内容都已经给出。想法是我需要创建包含连续插槽中的Student结构的动态数组。

据我所知,Valgrind认为在create_student中,malloc分配的内存太少,并且在测试函数(我们大学里面的服务器端的东西)时,我的名字字符串以某种方式指向NULL指针,并且超出了内存边界。

我试了几种方法,这给由编译器错误或警告(代码::块),并如预期,但仍Valgrind的不喜欢它的工作原理..

谢谢你在前进!

Valgrind的输出:

==358== Invalid read of size 8 
==358== at 0x4016CB: test_create_student (test_source.c:38) 
==358== by 0x406340: srunner_run_all (in /tmc/test/test) 
==358== by 0x40288A: tmc_run_tests (tmc-check.c:121) 
==358== by 0x402544: main (test_source.c:310) 
==358== Address 0x518d768 is 0 bytes after a block of size 56 alloc'd 
==358== at 0x4C244E8: malloc (vg_replace_malloc.c:236) 
==358== by 0x402C5D: create_student (source.c:18) 
==358== by 0x401690: test_create_student (test_source.c:35) 
==358== by 0x406340: srunner_run_all (in /tmc/test/test) 
==358== by 0x40288A: tmc_run_tests (tmc-check.c:121) 
==358== by 0x402544: main (test_source.c:310) 
==358== 
==358== Invalid read of size 1 
==358== at 0x4C25D94: strcmp (mc_replace_strmem.c:426) 
==358== by 0x4016DC: test_create_student (test_source.c:38) 
==358== by 0x406340: srunner_run_all (in /tmc/test/test) 
==358== by 0x40288A: tmc_run_tests (tmc-check.c:121) 
==358== by 0x402544: main (test_source.c:310) 
==358== Address 0x0 is not stack'd, malloc'd or (recently) free'd 
==358== 
==358== 
==358== Process terminating with default action of signal 11 (SIGSEGV) 
==358== Access not within mapped region at address 0x0 
==358== at 0x4C25D94: strcmp (mc_replace_strmem.c:426) 
==358== by 0x4016DC: test_create_student (test_source.c:38) 
==358== by 0x406340: srunner_run_all (in /tmc/test/test) 
==358== by 0x40288A: tmc_run_tests (tmc-check.c:121) 
==358== by 0x402544: main (test_source.c:310) 
==358== If you believe this happened as a result of a stack 
==358== overflow in your program's main thread (unlikely but 
==358== possible), you can try to increase the size of the 
==358== main thread stack using the --main-stacksize= flag. 
==358== The main thread stack size used in this run was 8388608. 

这是源文件:

#include "source.h" 
#include "string.h" 
#include "stdlib.h" 

/* Parameters: 
* s: pointer to the Students main structure (allocated by caller) 
* name: name of student 
* id: Student ID 
* age: age 
* course: course code 
* Returns: pointer to the student element in the array 
*/ 
Student *create_student(Students *s, const char *name, const char *id, 
     unsigned char age, const char *course) 
{ 
    if(s->count == 0){ 
     s->array = malloc(sizeof(Student)); 
     if(s->array == NULL) 
      return NULL; 
    } 
    if(s->count > 0){ 
     Student *nptr = realloc(s->array, (s->count+1)*sizeof(Student)); 
     if(nptr == NULL) 
      return NULL; 
     else 
      s->array = nptr; 
    } 

    s->array[s->count].name = malloc((strlen(name)+1));     /*Allocating memory for name pointer*/ 
    if(s->array[s->count].name == NULL) 
     return NULL; 
    memcpy(s->array[s->count].name, name, strlen(name));    /*Copying name string to the *name array*/ 
    s->array[s->count].name[strlen(name)] = '\0'; 

    if(strlen(id) > 8|| strlen(course) > 16)       /*Checks if the strings are correct length*/ 
     return NULL; 
    memcpy(s->array[s->count].id, id, strlen(id));     /*Copying rest of the files*/ 
    s->array[s->count].id[strlen(id)] = '\0'; 
    memcpy(s->array[s->count].course, course, strlen(course)); 
    s->array[s->count].course[strlen(course)] = '\0'; 
    s->array[s->count].age = age; 
    s->array[s->count].points = NULL; 
    s->array[s->count].numPoints = 0; 

    s->count++;               /*Count is incremented by one as the first student is created*/ 
    s->array = &s->array[0];           /*Now *array points at the first entry in the array*/ 

    return &s->array[s->count];           /*Returns newly created pointer to the student*/ 
} 


/* Parameters: 
* s: pointer to the Students main structure 
* id: Student ID to be looked for 
* course: Course code to be looked for 
* Returns: pointer to the student element in array, if found. NULL if not found 
*/ 
Student *find_student(Students *s, const char *id, const char *course) 
{ 
    Student *ptr = s->array;        /*Creating pointer that points at the current student structure (starts from the beginning)*/ 
    int r1, r2; 
    for(unsigned int i = 0; i < s->count; i++){ 
     r1 = strcmp(ptr->course, course);     /*Checks for ID and course number*/ 
     r2 = strcmp(ptr->id, id); 
     if(r1 == 0 && r2 == 0){ 
      return ptr;          /*Returns pointer to the student structure if matches*/ 
     } 
     ptr++; 
    } 
    return NULL;           /*Returns NULL if no such student found*/ 
} 

/* Parameters: 
* s: pointer to the Students main structure 
* id: Student ID to be deleted 
* course: Course from which student is deleted 
* Returns: 1 if deletion was successful, 0 if not (e.g. student not found) 
*/ 
int delete_student(Students *s, const char *id, const char *course) 
{ 
    Student *st0 = s->array;          /*Pointer at the first element in the array*/ 
    Student *stl = st0;            /*Pointer at the last element in the array*/ 
    for(int i = 0; i < (s->count-1); i++) 
     stl++; 
    if(find_student(s, id, course) == st0){       /*1. Deleting the first element in the array*/ 
     s->count--; 
     free(st0->name); 
     for(int i = 0; i < s->count; i++) 
      memcpy(st0+i, st0+(i+1), sizeof(Student)); 
     s->array = realloc(s->array, (s->count)*sizeof(Student)); 
     return 1; 
    } 
    else if(find_student(s, id, course) == stl){     /*2. Deleting the last element in the array*/ 
     s->count--; 
     free(stl->name); 
     s->array = realloc(s->array, (s->count)*sizeof(Student)); 
     return 1; 
    } 
    else if(find_student(s, id, course) != NULL){     /*3. Deleting the element in the middle of array*/ 
     int a = 0; 
     while(st0 != find_student(s, id, course)){ 
      a++; 
      st0++; 
     } 
     free(st0->name); 
     s->count--; 
     for(int i = 0; i < s->count-a; i++){ 
      memcpy(st0+i, st0+(i+1), sizeof(Student)); 
     } 
     s->array = realloc(s->array, (s->count)*sizeof(Student)); 
     return 1; 
    } 
    return 0; 
} 


/* Parameters: 
* s: pointer to the Students main structure 
* id: student ID to set the points 
* course: course ID to set the points 
* points: array of points to be set to the student (will replace previous entry) 
* len: length of the points array 
* Returns: 1 if setting points was successful, 0 if not (e.g. student not found) 
*/ 
int set_points(Students *s, const char *id, const char *course, const float *points, int len) 
{ 
    Student *st = find_student(s, id, course); 
    if(st != NULL){ 
     if(st->points == NULL){ 
      st->points = malloc(len * sizeof(int)); 
      for(int i = 0; i < len; i++) 
       st->points[i] = points[i]; 
      st->numPoints = len; 
      return 1; 
     } 
     else{ 
      st->points = realloc(st->points, len * sizeof(int)); 
      for(int i = 0; i < len; i++) 
       st->points[i] = points[i]; 
      st->numPoints = len; 
      return 1; 
     } 
    } 
    return 0; 
} 

这是source.h:

typedef struct student Student; 

struct student { 
    char *name; // name of the student 
    char id[8]; // null-terminated student ID 
    unsigned char age; 
    char course[16]; // null-terminated course code; 
    float *points; // pointer to dynamic array of exercise points 
    unsigned int numPoints; // length of the above array 
}; 

typedef struct { 
    unsigned int count; // size of the students array 
    Student *array; // pointer to the first element in the array 
} Students; 

Student *create_student(Students *s, const char *name, const char *id, 
     unsigned char age, const char *course); 
Student *find_student(Students *s, const char *id, const char *course); 
int delete_student(Students *s, const char *id, const char *course); 
int set_points(Students *s, const char *id, const char *course, const float *points, int len); 

这是主要的:

#include <stdio.h> 
#include <assert.h> 
#include <string.h> 
#include "source.h" 

void print_students(Students *s) 
{ 
    Student *st = s->array; 
    for (unsigned int i = 0; i < s->count; i++) { 
     printf("%s (%s), Course: %s, Age: %d\n", st->name, st->id, st->course, st->age); 
     if (st->numPoints) { 
      printf(" -- Points: "); 
      for (unsigned int j = 0; j < st->numPoints; j++) 
       printf("%f ", st->points[j]); 
      printf("\n"); 
     } 
     st++; 
    } 
} 

void initialize_reg(Students *reg) { 
    assert(reg != NULL); 
    reg->count = 0; 
    reg->array = NULL; 
    create_student(reg, "Teemu Teekkari", "00000A", 20, "ELEC-A1100"); 
    create_student(reg, "Matti Meikäläinen", "12345B", 28, "ELEC-A1100"); 
    create_student(reg, "Wow", "33333C", 28, "ELEC-A1100"); 
    create_student(reg, "Much Student", "98765H", 28, "ELEC-A1100"); 
    create_student(reg, "Such course", "12121R", 28, "ELEC-A1111"); 
    create_student(reg, "Amaze", "11111T", 28, "ELEC-A1111"); 
} 

int main() 
{ 
    Students s; 
    s.count = 0; 
    s.array = NULL; 

    // create a group of students using create_student 
    initialize_reg(&s); 
    print_students(&s); 

    // Try find_student 
    Student *sf3 = find_student(&s, "33333C", "ELEC-A1100"); 
    Student *sf6 = find_student(&s, "11111T", "ELEC-A1111"); 
    if (!sf3) { 
     printf("Did not find existing student 33333C\n"); 
    } else if (strcmp(sf3->id, "33333C")) { 
     printf("Incorrect student ID %s when should have been 33333C\n", sf3->id); 
    } 
    if (!sf6) { 
     printf("Did not find existing student 11111T\n"); 
    } else if (strcmp(sf6->id, "11111T")) { 
     printf("Incorrect student ID %s when should have been 11111T\n", sf6->id); 
    } 

    // Try delete_student with existing student 
    if (!delete_student(&s, "12121R", "ELEC-A1111")) { 
     printf("Delete student failed for existing student\n"); 
    } 

    printf("-----\n"); 
    float p[] = {3.0, 1.0, 4.0, 4.5}; 
    set_points(&s, "00000A", "ELEC-A1100", p, 4); 
    print_students(&s); 
    printf("-----\n"); 

    // Try delete_student with non_existing student 
    delete_student(&s, "33333C", "ELEC-A1100"); 
    print_students(&s); 
} 

这是test_source到Valgrind的是指:

#include <check.h> 
#include "tmc-check.h" 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <assert.h> 
#include <time.h> 
#include "../src/source.h" 

void release_memory(Students *s) { 
    unsigned int i; 
    if (s->array) { 
     for (i = 0; i < s->count; i++) { 
      Student *st = &(s->array[i]); 
      if (st->name) 
       free(st->name); 
      if (st->points) 
       free(st->points); 
     } 
     free(s->array); 
    } 
} 

START_TEST(test_create_student) { 
    Students reg; 
    //assert(reg != NULL); 
    reg.count = 0; 
    reg.array = NULL; 
    char buf[160]; 

    //char *name = malloc(strlen("Teemu Teekkari") + 1); 
    //strcpy(name, "Teemu Teekkari"); 
    char *name = "Teemu Teekkari"; 

    Student *s1 = create_student(&reg, name, "00000A", 20, "ELEC-A1100"); 
    fail_unless(s1 != NULL, "[Task 3.4.a] create_student returned NULL.\n"); 

    if (strcmp(name, s1->name)) { 
     sprintf(buf, "[Task 3.4.a] Student name should be %s, was %s.\n", name, s1->name); 
     release_memory(&reg); 
     fail(buf); 
    } 

    if (strcmp("00000A", s1->id)) { 
     sprintf(buf, "[Task 3.4.a] Student ID should be %s, was %s.\n", "00000A", s1->id); 
     release_memory(&reg); 
     fail(buf); 
    } 

    if (s1->age != 20) { 
     sprintf(buf, "[Task 3.4.a] Student age should be 20, was %d\n.", s1->age); 
     release_memory(&reg); 
     fail(buf); 
    } 

    if (strcmp("ELEC-A1100", s1->course)) { 
     sprintf(buf, "[Task 3.4.a] Course code not should be %s, was %s.\n", "ELEC-A1100", s1->course); 
     release_memory(&reg); 
     fail(buf); 
    } 

    if (s1->points != NULL) { 
     sprintf(buf, "[Task 3.4.a] Points array should be NULL, was %p.\n", s1->points); 
     release_memory(&reg); 
     fail(buf); 
    } 

    if (s1->numPoints != 0) { 
     sprintf(buf, "[Task 3.4.a] numPoints should be 0, was %d.\n", s1->numPoints); 
     release_memory(&reg); 
     fail(buf); 
    } 

    //free(name); 
    //fail_unless(!strcmp("Teemu Teekkari", s1->name), "[Task 17.1] Student name was not allocated from heap."); 

    if (reg.count != 1) { 
     sprintf(buf, "[Task 3.4.a] After adding a student, student count should be 1, was %d.\n", 
       reg.count); 
     release_memory(&reg); 
     fail(buf); 
    } 

    if (reg.array != s1) { 
     release_memory(&reg); 
     fail("[Task 3.4.a] After adding one student, the returned value does not point to the beginning of array.\n"); 
    } 

    Student *s2 = create_student(&reg, "Peppilotta Sikuriina Rullakartiina Kissanminttu Efraimintytar Pitkatossu", "12345B", 10, "ELEC-A1100"); 
    if ((reg.array) + 1 != s2) { 
     release_memory(&reg); 
     fail("[Task 3.4.a] After adding second student, the returned value does not point to the second array member.\n"); 
    } 

    if (reg.count != 2) { 
     sprintf(buf, "[Task 3.4.a] After adding second student, the student count should be 2, was %d.\n", 
       reg.count); 
     release_memory(&reg); 
     fail(buf); 
    } 

#if 0 
    Student *s3 = create_student(&reg, "Ylimaaraisia Merkkeja", "99999Ffoofoofoofoo", 60, "ELEC-A1111-even-16-characters-is-too-much-for-a-course-code"); 
    assert(s3 != NULL); 

    if (strcmp("99999Ff", s3->id)) { 
     sprintf("[Task 3.4.a] Too long student id truncated incorrectly: %s, should be %s\n", 
       s3->id, "99999Ff"); 
     release_memory(&reg); 
     fail(buf); 
    } 
    if (strcmp("ELEC-A1111-even", s3->course)) { 
     sprintf(buf, "[Task 3.4.a] Too long course code truncated incorrectly: %s, should be %s\n", 
       s3->course, "ELEC-A1111-even"); 
     release_memory(&reg); 
     fail(buf); 
    } 
#endif 
    release_memory(&reg); 
} 

END_TEST 

Students *initialize_reg(Students *reg) { 
    //Students *reg = malloc(sizeof(Students)); 
    assert(reg != NULL); 
    reg->count = 0; 
    reg->array = NULL; 
    create_student(reg, "Teemu Teekkari", "00000A", 20, "ELEC-A1100"); 
    create_student(reg, "Matti Meikäläinen", "12345B", 28, "ELEC-A1100"); 
    create_student(reg, "Wow", "33333C", 28, "ELEC-A1100"); 
    create_student(reg, "Much Student", "98765H", 28, "ELEC-A1100"); 
    create_student(reg, "Such course", "12121R", 28, "ELEC-A1111"); 
    create_student(reg, "Amaze", "11111T", 28, "ELEC-A1111"); 
    return reg; 
} 

START_TEST(test_find_student) { 
    Students regb; 
    char buf[160]; 
    Students *reg = initialize_reg(&regb); 
    Student *sf3 = find_student(reg, "33333C", "ELEC-A1100"); 
    Student *sf6 = find_student(reg, "11111T", "ELEC-A1111"); 

    if (sf3 == NULL) { 
     release_memory(reg); 
     fail("[Task 3.4.b] find_student returned NULL for existing student ID %s.\n", "33333C"); 
    } 

    if (strcmp(sf3->id, "33333C")) { 
     sprintf(buf, "[Task 3.4.b] find_student returned student with wrong id. Searched for: %s, returned: %s", "33333C", sf3->id); 
     release_memory(reg); 
     fail(buf); 
    } 

    if (sf6 == NULL) { 
     release_memory(reg); 
     fail("[Task 3.4.b] find_student returned NULL for existing student %s.\n", "11111T"); 
    } 

    if (strcmp(sf6->id, "11111T")) { 
     sprintf(buf, "[Task 3.4.b] find_student returned student with wrong id. Searched for: %s, returned: %s", "11111T", sf6->id); 
     release_memory(reg); 
     fail(buf); 
    } 

    if (NULL != find_student(reg, "98989D", "ELEC-A1112")) { 
     release_memory(reg); 
     fail("[Task 3.4.b] find_student should return NULL for nonexistent students.\n"); 
    } 

    /* fail_unless(NULL == find_student(reg, "98989D", "ELEC-A1100"), "[Task 17.2] find_student should return NULL for nonexistent students."); 
     fail_unless(NULL == find_student(reg, "33333C", "ELEC-A1112"), "[Task 17.2] find_student should return NULL for nonexistent students."); 
     fail_unless(NULL == find_student(reg, "33333C", "ELEC-A1111"), "[Task 17.2] find_student should return NULL for nonexistent students.");*/ 
    release_memory(reg); 
} 

END_TEST 


START_TEST(test_delete_student) { 
    char buf[160]; 
    Students regb; 
    Students *reg = initialize_reg(&regb); 
    if (reg->count != 6) { 
     sprintf(buf, "[Task 3.4.c] Wrong student count after adding 6 students, you have %d\n.", 
       reg->count); 
     release_memory(reg); 
     fail(buf); 
    } 

    if (!delete_student(reg, "11111T", "ELEC-A1111")) { 
     sprintf(buf, "[Task 3.4.c] delete_student() failed for existing student 11111T.\n"); 
     release_memory(reg); 
     fail(buf); 
    } 

    if (reg->count != 5) { 
     sprintf(buf, "[Task 3.4.c] After deleting one student, student count should be 5, you had %d.\n", 
       reg->count); 
     release_memory(reg); 
     fail(buf); 
    } 

    if (!delete_student(reg, "33333C", "ELEC-A1100")) { 
     sprintf(buf, "[Task 3.4.c] delete_student() failed for existing student 33333C.\n"); 
     release_memory(reg); 
     fail(buf); 
    } 
    //fail_unless(reg->count == 4, "[Task 17.3] Wrong student count after deletion."); 

    assert((reg->array + 2) != NULL); 

    if (strcmp((reg->array + 2)->id, "98765H")) { 
     sprintf(buf, "[Task 3.4.c] After deleting student 33333C, student %s should be in 3rd array position. You have %s.\n", "98765H", (reg->array + 2)->id); 
     release_memory(reg); 
     fail(buf); 
    } 

    if (delete_student(reg, "33330C", "ELEC-A1101")) { 
     release_memory(reg); 
     fail("[Task 3.4.c] delete_student() should have failed for nonexisting student 33330C.\n"); 
    } 
    /*fail_unless(delete_student(reg, "00000A", "ELEC-A1111") == 0, "[Task 17.3] delete_student() should have failed for nonexisting student."); 
    fail_unless(delete_student(reg, "12121R", "ELEC-A1100") == 0, "[Task 17.3] delete_student() should have failed for nonexisting student."); 
    fail_unless(delete_student(reg, "00000A", "ELEC-A1100"), "[Task 17.3] delete_student() failed for existing student 00000A."); 
    fail_unless(delete_student(reg, "12345B", "ELEC-A1100"), "[Task 17.3] delete_student() failed for existing student 12345B."); 
    fail_unless(delete_student(reg, "98765H", "ELEC-A1100"), "[Task 17.3] delete_student() failed for existing student 98765H."); 
    fail_unless(delete_student(reg, "12121R", "ELEC-A1111"), "[Task 17.3] delete_student() failed for existing student 12121R."); 

    fail_unless(reg->count == 0, "[Task 17.3] Course register should be empty after deleting all students.");*/ 

    release_memory(reg); 
} 

END_TEST 


void pr_array(char *buf, float *arr, int n) { 
    char b[40]; 
    sprintf(buf, "{"); 
    while (n--) { 
     sprintf(b, "%.1f", *arr++); 
     if (n) 
      strcat(b, ", "); 
     strcat(buf, b); 
    } 
    strcat(buf, "}"); 
} 

START_TEST(test_set_points) { 
    Students regb; 
    Students *reg = initialize_reg(&regb); 
    char arrbuf[80]; 
    char buf[160]; 
    float p[4]; 
    int i; 
    for (i = 0; i < 4; i++) { 
     p[i] = (float)(rand() % 10)/2; 
    } 
    pr_array(arrbuf, p, 4); 

    if (!set_points(reg, "00000A", "ELEC-A1100", p, 4)) { 
     sprintf(buf, "[Task 3.4.d] set_points() returned 0 for student 00000A with array %s, but it should have succeeded.\n", 
       arrbuf); 
     release_memory(reg); 
     fail(buf); 
    } 
    Student *st = &(reg->array[0]); 

    if (st->points == NULL) { 
     sprintf(buf, "[Task 3.4.d] Points array not created for array %s (is still NULL).\n", 
       arrbuf); 
     release_memory(reg); 
     fail(buf); 
    } 

    char arr2[80]; 
    pr_array(arr2, st->points, 4); 
    for (i = 0; i < 4; i++) { 
     if (st->points[i] != p[i]) { 
      sprintf(buf, "[Task 3.4.d] Point array differs. Should be %s. You have %s\n", 
        arrbuf, arr2); 
      release_memory(reg); 
      fail(buf); 
     } 
    } 
    /*float q[] = {2, 5, 1, 6, 12, 1}; 
    fail_unless(set_points(reg, "00000A", "ELEC-A1100", q, 6) == 1, "[Task 17.4] set_points() did not return 1 on success or failed when it was not supposed to"); 
    fail_unless(st->points != NULL, "[Task 17.4] Points array for student not created"); 
    fail_unless(st->points[4] == 12, "[Task 17.4] Setting points failed on student"); 
    fail_unless(set_points(reg, "00000A", "ELEC-A1111", p, 3) == 0, "[Task 17.4] set_points() did not return 0 on failure");*/ 

    release_memory(reg); 
} 

END_TEST 


int main(int argc, const char *argv[]) { 
    srand((unsigned) time(NULL)); 
    Suite *s = suite_create("Test-3.4"); 

    /* TODO: define tests */ 
    tmc_register_test(s, test_create_student, "3.4.a"); 
    tmc_register_test(s, test_find_student, "3.4.b"); 
    tmc_register_test(s, test_delete_student, "3.4.c"); 
    tmc_register_test(s, test_set_points, "3.4.d"); 

    return tmc_run_tests(argc, argv, s); 
} 
+1

当您复制字符串时,为什么不使用'strcpy'而不是'memcpy'加上添加终止字符?甚至使用'strdup'使它更简单?就像's-> array [s-> count] .name = strdup(name);' –

+1

另外,你还要检查'id'和'course'字段是错误的。它们允许字符串长度分别为8和16,这样就不会留下字符串终结符的空间。哦,在这里给一个简单的['strcpy'](http://en.cppreference.com/w/c/string/byte/strcpy)会更好。 –

+0

我试过使用strcpy,它仍然给出相同的Valgrind错误。并且所有的ID都是6 + \ 0的长度和10 + \ 0的过程长度,所以终止NULL应该在id和course数组中。 – user3332718

而且随着测试的源代码,用我最后的评论相结合,它现在很容易看出问题:

您返回Student指针点超出分配的内存。

在此点上,create_student函数返回,您已增加s->count,因此它是“数组”中的条目数s->array。但大小数组索引是零基的,那时最大索引是s->count - 1

+0

哦,我的上帝,它终于奏效!非常非常感谢你!我觉得很愚蠢,浪费了3天的时间盯着代码,试图找到问题,然后只是这个小事情导致了这个...... C是无情的。再次感谢你! – user3332718

create_student()函数结束与:

s->count++; /*Count is incremented by one as the first student is created*/ 
s->array = &s->array[0]; /*Now *array points at the first entry in the array*/ 
return &s->array[s->count]; /*Returns newly created pointer to the student*/ 

我对这个代码epically持怀疑态度。

第一行很好;现在存储的学生比在功能运行之前还多。虽然评论被打破了。

第二行中断,它重新分配array,一个新分配的动态指针。你永远不应该那样做。幸运的是,这是一个不可操作的设置。评论意味着你认为它做了一些事情,这使得它很可怕。

第三行是超级可怕的;它会返回一个指向的指针,一旦通过数组,请记住count已递增。

如果调用count == 0,函数malloc() S代表单Student空间,然后返回一个指向第二元件中的一个的阵列。坏!