【问题标题】:Stack smashing detected on file closing文件关闭时检测到堆栈粉碎
【发布时间】:2021-05-10 16:54:38
【问题描述】:

我不明白为什么它会出错。尽管从文件中读取的一切都很好。 检测到错误 *** 堆栈粉碎 ***:已终止 中止(核心转储)。

{
    FILE *set = fopen("data.bin", "rb");
    if (set == NULL) {
        fprintf(stderr, "I/O ERROR: Can't read from file.\n");
        exit(1);
    }
    int number;
    Enrollee e;
    fread(&number, sizeof(number), 1, set);
    for (int i = 0; i < number; i++) {
        if (fread(&(e.id)           , sizeof(e.id)           , 1       , set) != 1       ) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        if (fread(&(e.surname)      , sizeof(e.surname)      , STR_SIZE, set) != STR_SIZE) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        if (fread(&(e.initials)     , sizeof(e.initials)     , STR_SIZE, set) != STR_SIZE) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        if (fread(&(e.gender)       , sizeof(e.gender)       , 6       , set) != 6       ) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        if (fread(&(e.schoolNumber) , sizeof(e.schoolNumber) , 1       , set) != 1       ) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        if (fread(&(e.medal)        , sizeof(e.medal)        , 1       , set) != 1       ) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        if (fread(&(e.essayResults) , sizeof(e.essayResults) , 1       , set) != 1       ) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        if (fread(&(e.math)         , sizeof(e.math)         , 1       , set) != 1       ) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        if (fread(&(e.language)     , sizeof(e.language)     , 1       , set) != 1       ) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        if (fread(&(e.fisics)       , sizeof(e.fisics)       , 1       , set) != 1       ) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        if (fread(&(e.informatics)  , sizeof(e.informatics)  , 1       , set) != 1       ) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        if (fread(&(e.history)      , sizeof(e.history)      , 1       , set) != 1       ) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        if (fread(&(e.socialScience), sizeof(e.socialScience), 1       , set) != 1       ) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        if (fread(&(e.biology)      , sizeof(e.biology)      , 1       , set) != 1       ) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        if (fread(&(e.chemistry)    , sizeof(e.chemistry)    , 1       , set) != 1       ) { fprintf(stderr, "I/O ERROR: Something went wrong! Failed to read, possibly out of memory\n"); exit(3); };
        printf("%d %.20s %.3s %.2s %d %c %c %d %d %d %d %d %d %d %d\n",
        e.id,
        e.surname,
        e.initials,
        e.gender,
        e.schoolNumber,
        e.medal,
        e.essayResults,
        e.math, e.language, e.fisics, e.informatics, e.history, e.socialScience, e.biology, e.chemistry);
    }
    fseek(set, 0, 0);
    fclose(set);
}

【问题讨论】:

  • 请发帖minimal reproducible example。顺便说一句,您是否注意到代码大量的代码复制,这也使您的代码难以阅读?将错误处理放到一个单独的函数中。
  • 不知道 Enrollee 的定义很难说。但我会专注于字符串,您对它们的阅读假设sizeof(e.surname)==1 这可能不是真的。 fread 将 sizenmemb 相乘并读取那么多字节。
  • 这看起来不对:sizeof(e.surname) , STR_SIZE, 但没有Enrollee 的定义我们无法判断
  • 此代码在 Enrollee 中超出范围时会破坏堆栈。 e.initials 不能很好,6 性别似乎是关闭的。
  • 你为什么删除显示Enrollee定义的评论?请编辑您的问题并插入。

标签: c file


【解决方案1】:

你所有的字符串读取都是错误的。

fread(&(e.gender)       , sizeof(e.gender)       , 6       , set)

说:阅读 6 个元素。每个元素都是sizeof(e.gender) 字节。

由于gender 是一个数组,即char gender[6]sizeof(e.gender) 返回 6。

所以您的代码读取 6 * 6 = 36 个字节。你只想要 6 个。

做:

fread(&(e.gender)       , sizeof(char)       , 6       , set)

或更好

fread(&(e.gender)       , sizeof(gender[0])       , sizeof(gender)       , set)

这适用于你所有的字符串。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多