0

I had made a program in c in Ubuntu using gcc-7.I had sambleb.out file which is executable.I want to copy that file using c programming. here is the program.

#include <stdio.h>
int main()
{
    FILE *fp;
    fp = fopen("sampleb.out","rb");

    FILE *fpcp;
    fpcp = fopen("cp-of-sampleb.out","wb");

    char forcp;
    while (1)
    {
        forcp = fgetc(fp);
        if(forcp == EOF)
            break;
        fputc(forcp, fpcp);
    }

    fclose(fp);
    fclose(fpcp);
}

when I compile the program and execute the it, I get segmentation fault.

 $ a.out && chmod a+x cp-of-sampleb.out
 $ ./cp-of-sampleb.out
 Segmentation fault

here is the content of cp-of-sample.out

$ cat cp-of-sampleb.out 
ELF>0@@@@8  @@@@@@��88@8@@@,, `` ( 
((`(`��TT@T@DDP�td@@44Q�tdR�td``��/lib64/ld-
linux-x86-64.so.2GNU GNUX�T3�O���t�R�b�Ss�F
                                                  $ 
libc.so.6printf__libc_start_main__gmon_start__GLIBC_2.2.5ui 
3�`` `H�H�%
             H��t�CH��

and content of sampleb.out

$ cat sampleb.out 
ELF>0@@@@8  @@@@@@��88@8@@@,, `` ( 
((`(`��TT@T@DDP�td@@44Q�tdR�td``��/lib64/ld-
linux-x86-64.so.2GNU GNUX�T3�O���t�R�b�Ss�F
                                                  $ 
libc.so.6printf__libc_start_main__gmon_start__GLIBC_2.2.5ui 
3�`` `H�H�%
             H��t�CH���5
                          �%
                             @�%
                                 h������%

h������%�
]�8`��D]�fD�8`UH��8`H��H��H��H��?
H�H��t�H��tU�8`H=8`H��t�H��t
                                                ]�8`��]�fD�=a

uUH���~����O

]�D��@f.�UH��]��UH�忸@�������]�f.�DAWAVA��AUATL�% UH�- 
SI��I��L)�H�H���g���H��t 
1��L��L��D��A��H��H9�u�H�[]A\A]A^A_Ðf.���H�H��how are you I am 
fine this singale line is printed by multiline 
printf;4�����0���P����0��������zRx

�����*zRx

�$h���0FJ
U                                                                                         
�?;*3$"DW���A�C
Dd`���eB�B�E �B(�H0�H8�M@r8A0A(B BB�����@�@
�@` `���o�@@�@                                   �@
?
 `0�@�  ���o`@���o���oX@(`@@GCC: (Ubuntu 7.1.0-
5ubuntu2~16.04) 7.1.08@T@t@�@�@@X@`@    �@
�@
   �@
@0@�@�@@8@` `(`�``(`8`��
                                                       `@�@!
�@78`F `m@y`������(@���(`(���`�(`(8`8�08)8h�    P�

(I hadn't posted last line cause they were to many).Thus I can see that my program is coping only first 7 lines.It will be very helpful if you tell me what is wrong??? I am still noob.

  • 5
    `char forcp;` ==> `int forcp;`. Function `fgetc` returns `int` so that in binary data you can distinguish `0xFF` data from `-1` EOF. – Weather Vane Aug 04 '17 at 07:49
  • 2
    `chmode` is presumably a typo for `chmod`. You don't test that the files were opened successfully; that's always *bad* — **very** ***bad!*** – Jonathan Leffler Aug 04 '17 at 07:49
  • 3
    The [`fgetc`](http://en.cppreference.com/w/c/io/fgetc) function returns an `int`. This is important for the `EOF` check. – Some programmer dude Aug 04 '17 at 07:50
  • 1
    As for your crash, I recommend you read [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) by Eric Lippert, and learn how to use a debugger. – Some programmer dude Aug 04 '17 at 07:51

1 Answers1

2

First, any such program should check the result of fopen() before continuing. If you don't do this, you're potentially using a NULL pointer that's returned from fopen() in case of failure and your program will crash.

Your immediate problem is that you assign the return value of fgetc() to a char. fgetc() returns an int which either corresponds to the value of an unsigned char or is EOF, an int constant that is negative and distinct from any valid character.

What might happen when you compare EOF to a char is the following: Your char can be signed, so in a binary file, you could find a byte that is -1 with signed char. -1 is often used as the int (!) value of EOF, so your comparison will be true even though fgetc() did not return EOF.

Fix: Replace char forcp; with int forcp;.

That all said, it's very inefficient copying a file byte by byte. You should better use a buffer and fread()/fwrite() for copying, like in the following example that also adds proper error checking:

#include <stdio.h>

#define BUFFERSIZE 8192  // 8 kiB

int main(int argc, char **argv)
{
    if (argc != 3)
    {
        fprintf(stderr, "Usage: %s source dest\n", argv[0]);
        return 1;
    }

    FILE *src = fopen(argv[1], "rb");
    if (!src)
    {
        fprintf(stderr, "Error opening %s for reading.\n", argv[1]);
        return 1;
    }

    FILE *dst = fopen(argv[2], "wb");
    if (!dst)
    {
        fclose(src);
        fprintf(stderr, "Error opening %s for writing.\n", argv[2]);
        return 1;
    }

    char buf[BUFFERSIZE];
    int rc = 1; // <- failure
    do
    {
        size_t nread = fread(buf, 1, BUFFERSIZE, src);
        if (nread < BUFFERSIZE)
        {
            if (ferror(src))
            {
                fprintf(stderr, "Error reading from %s.\n", argv[1]);
                goto done;
            }
            if (!nread) break;
        }

        if (fwrite(buf, 1, nread, dst) < nread)
        {
            fprintf(stderr, "Error writing to %s.\n", argv[2]);
            goto done;
        }
    } while (!feof(src));

    rc = 0; // <- success

done:
    fclose(dst);
    fclose(src);
    return rc;
}