在 fread/fwrite 循环中出现分段错误,复制文件

Getting segmentation fault in fread/fwrite loop, copying file

提问人:Andrew Ricci 提问时间:10/3/2015 最后编辑:Andrew Ricci 更新时间:10/4/2015 访问量:889

问:

我要将文件从输入的源复制到输入的目的地。输入目标后大约 2 秒,我收到分段错误。输出文件已创建,因此正在工作。fopen()

我在网上看了一下,我看到了很多.对于这个问题,我更喜欢和,因为它更基本一些。c=getc(fp)fread()fwrite()

法典

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

//void rmnewline(char *string);
void remove_last_newline(char *str);

int main()
{
  char x[3];
  x[0]='y';
  int ch;

  while(x[0]=='y'||x[0]=='Y')
  {
    char source[256], destination[256];
    int *a;

    printf("Enter a source file: ");
    fgets(source, 256, stdin);
    if (source[254] == '\n' && source[255] == '\0') { while ( (ch = fgetc(stdin)) != EOF && ch != '\n'); }
    remove_last_newline(source);

    printf("Enter a destination file: ");
    fgets(destination, 256, stdin);
    if (destination[254] == '\n' && destination[255] == '\0') { while ( (ch = fgetc(stdin)) != EOF && ch != '\n'); }
    remove_last_newline(destination);

    FILE *sp, *dp;

    sp = fopen(source, "r");
    if (sp == NULL) { printf("ERROR: Could not open source file."); exit(1); }
    dp = fopen(destination, "w");
    if (dp == NULL) { printf("ERROR: Could not open destination file."); exit(1); }
    while(1)
    {
      fread(a, 1, 1, sp);
      if (feof(sp))
      break;
      fwrite(a, 1, 1, dp);
    }

    fclose(sp);
    fclose(dp);

    printf("Run Again?(y/n):");
    fgets(x, 2, stdin);
    while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
 }

}

/*void rmnewline(char *string)
{
    int i, l = strlen(string);

    for(i=0; i<=l; i++)
    {
      if(string[i] == '\0')
         return;
      if(string[i] == '\n')
     {
       string[i] == '\0';
       return;
     }
  }

}*/

void remove_last_newline(char *str) {
    if (*str == '\0') return; /* do nothing if the string is empty */
    while(str[1] != '\0') str++; /* search for the end of the string */
    if (*str == '\n') *str = '\0'; /* if the last character is newline, delete it */
}
C 分段 - 故障 fwrite fread feof

评论

6赞 MikeCAT 10/3/2015
您应该检查 的返回值。fopen
3赞 wildplasser 10/3/2015
fgets() 读取包含 \n 的行。您应该首先删除它。
0赞 Jongware 10/3/2015
这里的概念错误:(再次使用目标):它不是缓冲区中的最后一个字符可能是换行符,而是最后一个读取字符。if (source[254] == '\n' && source[255] == '\0')
1赞 Jongware 10/3/2015
“输出文件已创建,因此 fopen() 正在工作” - 但仅适用于写入文件。
1赞 chux - Reinstate Monica 10/3/2015
如果用户键入然后输入,则仅保存其 null 字符,为下一个输入函数留下 in。Yfgets(x, 2, stdin);"Y"'\n'stdin

答:

2赞 MikeCAT 10/3/2015 #1

fgets将读取的换行符存储在缓冲区中。

它可能会阻止打开“指定的文件”,并可能返回 .fopenfopenNULL

如果换行符位于缓冲区中,请删除它们。
这可以使用以下功能来完成:

void remove_last_newline(char *str) {
    if (*str == '\0') return; /* do nothing if the string is empty */
    while(str[1] != '\0') str++; /* search for the end of the string */
    if (*str == '\n') *str = '\0'; /* if the last character is newline, delete it */
}

请在读取文件名后传递 和 此函数。sourcedestination

评论

0赞 Andrew Ricci 10/3/2015
我会研究这个问题,但你能解释一下为什么 fread 不会读取我的新行字节吗?我不明白。如果文本文件是新行,如何添加新行?编辑:没关系,我明白
0赞 chux - Reinstate Monica 10/3/2015
候选人简化void remove_last_newline(char *str) { str[strcspn(str, "\n")] = '\0'; }
0赞 chux - Reinstate Monica 10/3/2015
@Andrew利玛窦失败了,因为失败了。这不是文件中换行的问题。鲁棒代码检查所有 IO 操作的结果(等)fread()fopen()fgets, fopen, fread
0赞 Andrew Ricci 10/3/2015
@chux,我在我自己的版本失败后添加了该方法。我仍然以赛格错误告终。
1赞 chux - Reinstate Monica 10/3/2015
@Andrew Ricci 是否检查了 IO 函数的所有返回值?如果没有,请节省调试时间并将测试添加到代码中。
1赞 Gangadhar 10/3/2015 #2

检查 的返回值。
程序在 SP 为 NULL 时发生 SEGFAULT。由于程序只尝试读取一个字节,因此不会有任何溢出的机会。
fopenfread(a, 1, 1, sp);

fopen失败,因为源由末尾的换行符组成。如果在调用 fopen 之前从源和目标中删除字符,则程序将正常工作。newline

0赞 chux - Reinstate Monica 10/4/2015 #3

主要问题是将 留在文件名中,然后以下失败,代码未检查返回值。其他 2 个答案很好地回答了这个问题,至少有 1 个值得接受。'\n'fopen()fopen()

随后的 OP 编辑更改为导致新故障。建议更改为int a[1]int *a

char a[1];