-2

I am trying to copy a files contents from source to destination. My code runs into a segmentation fault (after the destination file is opened). I would appreciate help debugging this issue.

FILE* source = fopen(fname, "r");
    char_u* ver2_fname = str_replace(fname, "version1", "version2");
    FILE* destination = fopen(ver2_fname, "w");
    free(ver2_fname);

    // transfer ver2_file_read from version 1 to version 2
    char character;
    while (!feof(source))
    {
        character = fgetc(source);
        fputc(character, destination);
    }
    fclose(source);
    fclose(destination);
Rafael
  • 1
  • 1
  • 4
    did you check the results of fopen and make sure the file pointer is not null? – OldProgrammer May 19 '22 at 01:33
  • 2
    Maybe the issue is with `str_replace()`. Can you add that? – 001 May 19 '22 at 01:33
  • 5
    Obligatory link: [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/a/26557243) – 001 May 19 '22 at 01:34
  • 1
    You don't even check if the `fopen`s succeed! If either of `source` or `destination` is NULL, bad things (like a seg fault) will happen. – William Pursell May 19 '22 at 01:37
  • Where exactly does the segmentation fault occur? You need to do basic error checking and basic debugging. For the latter run your program in a debugger to instantly tell you the exact line of code that triggers the seg fault. The debugger can also be used to examine program flow and variable values. – kaylum May 19 '22 at 01:39
  • Related: [How can I copy a file on Unix using C?](https://stackoverflow.com/questions/2180079/how-can-i-copy-a-file-on-unix-using-c) – jarmod May 19 '22 at 01:58
  • and copy byte-by-byte is the slowest method ever. Practical code never does that – phuclv May 19 '22 at 02:31
  • @phuclv Copying with `getchar`/`putchar` is not even close to the slowest. Reading one byte at a time with `read` is (probably) a thousand times slower. Using `fgets` or even `fread` is (probably) negligibly faster, if there is any improvement at all. `getchar` is usually implemented as a macro, and is highly optimized on most platforms. (`getchar` is not `fgetc`, but if the concern is about reading one byte at a time, it seems applicable) – William Pursell May 19 '22 at 03:22

2 Answers2

1

read the whole file and then write it
and don't use (!feof(source)) instead use ch != EOF

void copy_file_to(const char *src, const char *dest){
    
    char *__dest = NULL;
    
    FILE *file_ = fopen(src,"rb+");
 if(file_ == NULL){
        fprintf(stderr,"[ERROR]: UnKnown file [%s:%i] \n" ,__func__,__LINE__);
        exit(-1);
    }

   
    fseek(file_,0,SEEK_END);
    size_t file_size = ftell(file_);
    assert(file_size > 0);
    fseek(file_,0,SEEK_SET);

    __dest =  malloc((file_size) *sizeof(char));
    
     fread(__dest,1,file_size,file_);
    
    FILE *fpdest = fopen(dest,"wb+");
    fwrite(__dest, 1,file_size , fpdest);
    fclose(fpdest);
    fclose(file_);
    free(__dest);
}

or simply read like this:

    FILE *fp = fopen("./test.txt", "r+");
    int c= fgetc(fp);
    while (c != EOF) { 
        putchar(c); 
        c =fgetc(fp);
    }
    putchar('\n');
0

Segmentation Fault is caused by pointing to invalid memory location.

Hence please check the file name and you have permission for the memory to read the file in the context that you ae running the code. Check this by adding the following snippet just before the while loop:

  if (destination == NULL || source == NULL)
{
  printf ("Error! Could not open file\n");
  exit (-1);        // must include stdlib.h 
}

Apart from this when using feof(source) it is selecting the current file pointer location and as per the code it will select EOF also as a char.

Hence use following snippet :

do
{
    // Taking input single character at a time
    char c = fgetc(source);
    // Checking for end of file
    if (feof(source))
        break ;
    fputc (c, destination);
    printf("%c", c);
}  while(1);
Arun Chettoor
  • 1,021
  • 1
  • 12
  • 17