【问题标题】:C program crashes when calling fopen调用 fopen 时 C 程序崩溃
【发布时间】:2018-05-11 23:52:18
【问题描述】:

我是新来的,有一个问题无法通过互联网搜索解决。

当我再次调用 fopen 时,我的程序崩溃了。 只是一个小描述: 程序逐行读取文件。这些行有两种可能的格式,这就是为什么我必须区分它们。当文件处于格式中时,它对应于“else”分支。该程序可以正常工作而不会崩溃。 然而,导致“if”分支的另一种格式会导致崩溃。 我希望源代码的部分对你们来说已经足够了。

    FILE *f = fopen("DATA.txt", "a+");
    for (int m = 0; m<listsize; m += 1) {
    .
    .
    .
    FILE *CSV = fopen(name, "r");
    FILE *pufferfile = fopen("puf.txt", "w+");        
    .
    .
    .
    char puffer[90];
    while (fgets(puffer, 90, CSV))
    {
        fputs(puffer, pufferfile);
        fseek(pufferfile, 0, SEEK_SET);
        if ((strstr(puffer, "\"")) != NULL) {
            fscanf(pufferfile, "%d,%d/%d/%d,%d:%d:%d,\"  %[^'\"]%s%*[ \"]%s  %[^'\"]%s  %[^'\"]%s\n", &row, &month, &day, &year, &hours, &minutes, &seconds, w_h, we, wj, w_t);
            fseek(pufferfile, 0, SEEK_SET);
            h_0 = atoi(w_h);
            h_0 += ((float)atoi(w_h + (strlen(w_h)) - 1) / (float)10);
            hum = h_0;
            t_0 = atoi(w_t);
            t_0 += ((float)atoi(w_t + (strlen(w_t)) - 1) / (float)10);
            temp = t_0;
        }
        else {
            fscanf(pufferfile, "%d,%d/%d/%d,%d:%d:%d,%f,%s\n", &row, &month, &day, &year, &hours, &minutes, &seconds, &hum, we);
            fseek(pufferfile, 0, SEEK_SET);
            t_1 = (int)we[4] - 48;
            t_2 = (int)we[5] - 48;
            t_0 = (int)we[7] - 48;
            if (we[6] == ',') {
                t_3 = 0;
            }
            else {
                t_3 = t_0;
            }
            temp = t_1 * 10 + t_2 + t_3 / 10;
        }
        fprintf(f, "      %02d.%02d.%d\t ;\t %02d:%02d:%02d\t ;\t    %.1f\t ;\t %.1f\n", day, month, year, hours, minutes, seconds, temp, hum);

    }
    fclose(CSV);
    fclose(pufferfile);
    remove(name);


}
remove("puf.txt");
fclose(f);

int index = 0;
FILE *woo = fopen("DATA_daily.txt", "w+"); //HERE it crashes

编辑:对不起,我在代码中添加了几行,以便您更好地理解它。它不会直接在“if”分支中崩溃。关键是,如果程序读取以特定方式格式化的文件,它会选择 if 分支。然后在调用最后一个“fopen(“DATA_daily.txt”,“w +”);”时不知何故崩溃。 以程序选择“else”分支的方式格式化的相同数据不会导致崩溃。 让我简短地解释一下。我有一个文件名列表(大小为 lenghtsize)。 程序打开它,读取行并决定行的格式。 据此,它读取值并将其放入另一个文件(此处为“DATA.txt”)。 程序崩溃后,我可以看到文件 DATA.txt,它看起来很好。每一行都写在那里。

可能的 2 行格式如下所示:

1,4/4/2017,13:03:42,"  000028,9",       %RH,"  000023,1",  DEGREE C ---> resulting in the if-branch, causes crash
and
1,4/4/2017,13:03:42,28.9,       %RH,23.1,  DEGREE C  ---> resulting in the else branch, NO crash

【问题讨论】:

  • 您无法通过互联网解决编程错误。你用调试器解决它们..
  • 我在if 分支中没有看到任何fopen 调用,或者对可能调用fopen 的任何函数的任何调用,那么它怎么会在fopen 上崩溃分公司?
  • fclose(f); 有没有可能真的崩溃了? f 是什么?您之前在调用 fprintf 时也使用过它,但它似乎没有在任何地方初始化。
  • 您在使用之前没有检查来自fopen 的返回值。在第一次使用时关闭name 指定的文件后,您正在删除它,您是否在尝试再次打开它之前重新初始化?总是发布minimal reproducible example,它不必是你的整个程序,只要我们可以编译和验证发生了什么就足够了。当您生成 MCVE 时,您通常会自行发现问题。

标签: c crash


【解决方案1】:

我注意到您在“if”分支中的代码没有检查 fscanf 的返回值,这是首先要解决的问题。例如:

rc = fscanf(...);
if ( rc != 11 )
{
  // handle error
}

接下来我将检查您定义 w_h 和 w_t 的方式,并更改 %s。我刚刚检查了 MSDN 页面的 scanf() 并警告您必须始终为 %s 格式指定宽度(例如,使用 %32s 代替),以避免缓冲区溢出。

我还会确保 w_h 和 w_t 在将它们作为参数传递给 strlen 或 atoi 之前以空值结尾。例如:

char w_t[MAXLEN];
rc = fscanf(...);
if ( rc != 11 ) { /* handle error */ }
w_t[sizeof(w_t)-1] = '\0';
a = atoi(w_t);

但现在我注意到其实你写的

atoi(w_t + (strlen(w_t))

这不会做任何有用的事情,因为即使 w_t 成功地以空值终止,这也会将指向尾随空字节的指针传递给 atoi。我不知道 atoi 会怎么做,但它可能会返回 0。总是。

无论如何,这些都是我要解决的第一件事。正如其他人所说,如果您使用调试器,您将获得更快的速度。或 printfs。

【讨论】:

    猜你喜欢
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多