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

Getting segmentation fault in fread/fwrite loop, copying file

我要将文件从输入的源复制到输入的目标。输入目的地后约 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] == '[=11=]') { 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] == '[=11=]') { 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] == '[=11=]')
         return;
      if(string[i] == '\n')
     {
       string[i] == '[=11=]';
       return;
     }
  }

}*/

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

fgets将读入的换行符存入缓冲区

它可能会阻止 fopen 打开 "the specified file" 并且 fopen 可能 return NULL.

请删除缓冲区中的换行符。
这可以使用这个函数来完成:

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

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

检查 fopen 的 return 值。
该程序在 fread(a, 1, 1, sp); 处出现 SEGFAULT 当 SP 为 NULL 时会发生这种情况。由于程序试图只读取一个字节,因此不会有任何溢出的机会。

fopen 失败,因为源代码末尾包含换行符。如果您在调用 fopen 之前从源和目标中删除 newline 字符,您的程序将正常运行。

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

随后的 OP 编辑​​将 int a[1] 更改为 int *a,导致出现新错误。建议改为

char a[1];