【问题标题】:fclose() causes Segmentation Faultfclose() 导致分段错误
【发布时间】:2014-04-25 17:35:28
【问题描述】:

我一直在尝试在 C 中进行简单的文件处理,我想确保可以尝试使用此文件来访问该文件

#include<stdio.h>

main()
{
    CheckFile();
}

int CheckFile()
{
    int checkfile=0;

    FILE *fp1;
    fp1 = fopen("users.sav","r");

    if(fp1==NULL)
    {
        fopen("users.sav","w");
        fclose(fp1);
    }   
    if(checkfile!=0)printf("\nERROR ACCESSING FILE!\nNow exiting program with exit code: %d\n",checkfile);exit(1);
    return 0;
}

然后显示

Segmentation fault (core dumped)

但如果文件事先已经存在(例如,当我手动创建它或第二次运行程序时),它不会出现段错误

请帮忙。一周后的最后一个项目我需要这个,但我还没有掌握文件和指针的窍门。

我正在使用“gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1”

附言

我在另一个问题中看到了这个

在您的原始代码中无法保证 fopen 实际工作,在这种情况下它将返回 NULL 并且 fclose 不会被定义为行为。

那么我该如何检查它是否有效呢?

【问题讨论】:

  • 检查是正确的,只是不要fclose(fp1) if fp1 == NULL而是调用fp1 = fopen(..., "w");
  • 谢谢 :) 答案确实帮助我,到目前为止编码进展顺利。

标签: c file-io segmentation-fault fopen fclose


【解决方案1】:

fopen 返回一个FILE 指针。它将返回NULL 并设置全局errno 以指示错误。如果要检查errno,则必须在检查fopen是否返回NULL之后再检查。

if (fp1 == NULL)
{
    printf("fopen failed, errno = %d\n", errno);
}

否则,您可能会从其他地方获得errno,而不一定是您的fopen 电话。还包括errno.h。您也无需再次致电fopen("users.sav","w");。您没有重新分配指针,也没有再次检查它。

我看不出有什么理由在这里调用fclose,因为如果fopen 返回NULL,就没有什么可以关闭的了。这可能是您的段错误的原因。您正在尝试关闭空指针。 More information on fopen failures.

对您的代码的另一条评论。如果您要从CheckFile 返回int,它可能不应该是0 失败。我会返回 -1 以指示错误。更好的是,您可以返回全局 errno。此外,main 应该是 int main(),最后你应该是 return 0;。我并不特别关心您的CheckFile 命名方案。在 C 中,check_filecheckFile 的驼峰式会更好。

CheckFile 中,您的单行if 语句可以被格式化并且如果您在多行上格式化它可以更正常地工作。它并没有做你认为它目前所做的事情:

if(checkfile!=0)
{
   printf("\nERROR ACCESSING FILE!\nNow exiting program with exit code: %d\n", checkfile);
   exit(1);
}

此外,checkfile 永远不会在您的代码中的任何位置设置......除了零。所以if语句中的代码不会执行,句号。

【讨论】:

    【解决方案2】:

    这很正常,当你在 fp1 为 NULL 时调用 fclose(fp1)

    顺便说一句

    fopen("users.sav","w");
    

    没用,因为您没有将返回值分配给文件指针。这意味着将打开 users.sav 文件进行写入,但您将永远无法在其中写入任何内容。

    【讨论】:

      【解决方案3】:

      fclose 的手册页说 -

      如果流参数是 非法指针,或者是已经传递给前一个的描述符 调用 fclose()。

      错误出现在代码中的 if 块中。

      if(fp1==NULL)
      {
          fopen("users.sav","w");
          fclose(fp1);  // passing NULL to fclose invokes undefined behaviour
      }   
      

      【讨论】:

        【解决方案4】:

        我不太确定你想做什么,但直接的问题就在这里:

        if(fp1==NULL)
           fclose(fp1);
        

        在断言 fp1 为 NULL 后,您尝试在空指针上调用 close,这将导致分段错误。

        如果您只想验证文件是否存在,请尝试类似What's the best way to check if a file exists in C? (cross platform)

        【讨论】:

          【解决方案5】:

          另一个不相关的问题:

          这行可能不是你想要的:

          if(checkfile!=0)printf("\nERROR ACCESSING FILE!\nNow exiting program with exit code: %d\n",checkfile);exit(1);
          

          如果我们以正确的格式编写它,错误就会变得很明显:

          if (checkfile != 0)
            printf("\nERROR ACCESSING FILE!\nNow exiting program with exit code: %d\n",checkfile);
          
          exit(1);
          return 0 ;
          

          实际上,即使checkfile 为零,我们也会到达exit(1)

          你可能想要这个:

          if (checkfile != 0)
          {
            printf("\nERROR ACCESSING FILE!\nNow exiting program with exit code: %d\n",checkfile);
            exit(1); 
          }
          
          return 0 ;
          

          结论:正确格式化您的代码,许多错误会突然看起来很明显。

          【讨论】:

          • 您可能应该将此纳入您的其他答案,很好:)
          • @GIJoe:嗯,我不确定我是否应该这样做,因为这个问题与原始问题完全无关。
          • 我会.. 让你的答案更有说服力。
          • 它确实做到了......它还指出了我的代码中的许多其他我没有注意到的复杂情况(因此它不包含在我的问题中)但可能也会困扰我...我想这最终项目的事情真的让我很紧张。
          猜你喜欢
          • 1970-01-01
          • 2013-05-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-06
          • 2020-12-31
          • 2019-07-21
          相关资源
          最近更新 更多