【问题标题】:segmentation fault in files operation in CC中文件操作中的分段错误
【发布时间】:2014-02-24 14:21:48
【问题描述】:

我正在尝试使用动态内存分配从文件中删除多余的空格和换行符,但出现内存分段错误。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main(int argc,char **argv)
{
 FILE*fp;
 char ch;
 char *p;
 int i=0,size;
 if((fp = fopen(argv[1],"r"))==NULL) 
   {
    printf("Couldnt open file\n");
    return;
   }

 fseek(fp,0,2);
 size=ftell(fp);


 p = calloc(1,size+1);
 rewind(fp);
 while((p[i] = fgetc(fp))!=EOF)
 {
   i++;
 }
 p[i]=EOF;

 fclose(fp);

 for ( i=0; p[i]!=EOF; i++)
 {
  if (p[i] == ' ' && p[i+1] == ' ')
   {
     memmove(p+i,p+i+1,strlen(p+i+1));
     i--;
   }
  if (p[i] == '\n' && p[i+1] == '\n')
   {
     memmove(p+i,p+i+1,strlen(p+i+1));
     i--;
   }
 } //all extra spaces and newlines deleted..

fp = fopen("modified","w");
if (fp==NULL)
{
 printf("coudlnt create\n");
 return;
}

i=0; 

while((fputc(p[i],fp))!=EOF)
 {
    i++;
 }
   fclose(fp);
 }

我得到上述程序的分段错误(核心转储),如果我用 strlen(p+i+2) 修改 memmove 指令,那么它不会给出分段错误,而是卡在某种无限循环中。请告诉我我哪里出错了。

【问题讨论】:

  • (1) 为什么不使用正确的seek 定义值,例如SEEK_END:fseek(fp, 0, SEEK_END)? (2) 你的memmove 行看起来很可疑。你怎么知道strlen 什么时候会看到一个空字符作为字符串的结尾而不返回一个足够大的长度来超出你的文件缓冲区? (3) EOF 值是一个整数,所以如果你的文件中有一个 FF ,它会被视为 EOF,可能是无意的?这是 ASCII 文件还是二进制文件?
  • 您是否尝试过调试以查看错误发生在哪里,以及使用哪些数据?
  • 读取的文件是ASCII文件
  • 如果你想让我读这个问题,请使用一致的缩进和编码风格。
  • @Bartlomiej:对不起,我是 C 新手,不知道如何调试。

标签: c file gcc segmentation-fault


【解决方案1】:

您的文件读取已损坏; EOF 不是字符,因此您无法将字符与它进行比较并得到正确的结果。

改为使用fread() 读取整个文件。请注意,它可能会返回较短的长度,并且无论如何都需要循环。

也停止使用strlen();你知道从你分配缓冲区和读入文件开始的长度,所以像你一样一直使用strlen()在性能方面是非常浪费的。

【讨论】:

    【解决方案2】:

    不要将 char 与 EOF 进行比较,EOF 是 int。

    memmove 的整个想法很容易出错,为什么不在阅读时检查字节:

    int b;  // should be int
    
    while ((b = fgetc(fp)) != EOF) {
        char c = (char)b;
        if (p[i] == ' ' &&  c== ' ')  // the same for '\n'
           continue;
        p[++i] = c;
    }
    

    根本不需要任何memmove。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-19
      • 1970-01-01
      • 2019-08-10
      • 1970-01-01
      • 2015-04-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-07
      相关资源
      最近更新 更多