【问题标题】:Using realloc on array of structures在结构数组上使用 realloc
【发布时间】:2011-07-13 14:01:47
【问题描述】:

我已经为此挠头好几个小时了。这会将文本文件中的数据读取到结构中(每行有四个字符串,每行代表一个新学生)。我在 realloc 上遇到了段错误(接近尾声)。我怀疑我不明白指针是如何与 malloc/realloc 交互的。

struct student* createInitialStudentArray(FILE *fp) {
    char buf[20+1] = {0};
    int word = 1, studcount = 1;
    struct student* studentArray = malloc(sizeof(struct student));
    assert(studentArray != NULL);
    while (fscanf(fp, " %20s", buf) != EOF) {
        if (word % 4 == 1) {
            sscanf(buf, "%4d", &studentArray[studcount].studentID);
            word++;
        }
        else if (word % 4 == 2) {
            strcpy(studentArray[studcount].lastName, buf);
            word++;
        }
        else if (word % 4 == 3) {
            strcpy(studentArray[studcount].firstName, buf);
            word++;
        }
        else if (word % 4 == 0) {
            sscanf(buf, "%10lld", &studentArray[studcount].phoneNumber);
            word = 1;
            studcount++;
            studentArray = realloc(studentArray, studcount * sizeof(struct student));
            assert(studentArray != NULL);
        }
    }

    return studentArray;
}

是什么导致了这个段错误?

提前致谢,

格斯

【问题讨论】:

  • 尽管不是段错误的根本原因,但当 realloc 无法分配更多内存时,您使用 realloc 的方式可能会导致内存泄漏,因为它会返回 NULL 并且您会丢失指向前一个缓冲区的指针

标签: c arrays struct realloc


【解决方案1】:

如果您的数组有studcount 元素,那么studentArray[studcount] 超出了数组的末尾,并且不允许在那里写入。要访问的有效元素是0studcount-1。您应该在任何地方将 studentArray[studcount] 替换为 studentArray[studcount-1] 以写入最后一个元素。

请注意,这样做会在循环完成时为您提供一个比1 大的studcount 值,因为数组的最后一个元素始终为空或不完整。

正如 cmets 中的 pmg 所提到的,另一种解决方案是将 studcount 初始化为 0,这将解决上述两个问题,但是您需要确保在编写新的之前至少为 studcount+1 元素分配空间一个。

【讨论】:

    【解决方案2】:

    你的循环和 scanf 结构看起来不对..

    首先您读取一个字符串(while 条件中的scanf),然后是一个 int(word == 1),然后是另一个字符串(再次是 while 条件,word == 2),另一个字符串 ( while 条件再次,word == 3),最后是另一个字符串和 long long int (word == 4)。

    我会用开关重写你的内部循环

    /* pseudo-code */
    while (fgets(buf, sizeof buf, stdin)) {
        /* realloc here */
        chk = sscanf(buf, "%4d%20s%20s%10lld",
                    &studentArray[studcount].studentID,
                    studentArray[studcount].lastName,
                    studentArray[studcount].firstName,
                    &studentArray[studcount].phoneNumber);
        if (chk != 4) /* deal with error */;
    }
    

    【讨论】:

    • 谢谢,看起来更干净了。
    • 一个问题:sscanf 不记得字符串中的位置,对吧?所以每次调用 sscanf 都会从头开始,那我该如何扫描字符串中的第二个单词呢?
    • 嗯...是的,你是对的。最好一次性全部完成。修改答案:)
    猜你喜欢
    • 2014-07-21
    • 2013-06-11
    • 2015-02-13
    • 2021-03-04
    • 1970-01-01
    • 2020-03-07
    • 2012-09-19
    • 1970-01-01
    • 2012-09-28
    相关资源
    最近更新 更多