简体   繁体   中英

Malloc the size of file buffer base on an existing file

On my project, I need to copy the shared file into a directory which called share. My idea is to copy the contains of this file use fgets and fputs:

FILE *fp;
int size;
char *fileBuff

fseek(fp,0,SEEK_END );
size=ftell(fp);
printf("Size of %s: %d bytes.\n",path,size); // print correct size 
fileBuff=malloc(size); // mallocate the file buffer
printf("\nsize of file buffer is %d",sizeof(fileBuff)); //always print 4!!
while(!feof(fp)){
    fgets(fileBuff,size,fp); // put into file buffer

}
printf("\nsize of file buffer is %d",sizeof(fileBuff)); // also print 4!!

However, the file buffer cannot be mallocated, the size of this file buffer is always 4. what happen?

update: it seems have some misunderstanding. the sizeof() if just for my to check whether there is any thing stored in the file buffer. I do try strlen(fileBuff), and it gives me 1, always.

This is wrong: sizeof(fileBuff) . This will be the size of the pointer, which is 4 on your system.

You cannot use sizeof to "extract" the size of a block of memory returned by malloc() . You can't use anything to extract that size, it's simply not possible in (standard) C. You need to use the size value, ie the argument to malloc() .

Also, ftell() returns long , not int and both malloc() and the various I/O calls can fail, which you need to take into account.

In my opinion, it's not a good idea to use a buffer the size of the file to do a simple copy; it's much better to use a "reasonable" buffer (whose exact optimal size depends on a lot of factors) and then do repeated read-write pairs in a loop until you've streamed through the entire file.

UPDATE Further points about your code:

  1. You talk about using strlen() but the code shows sizeof after the fread() , too.
  2. You talk about using sizeof to "check" if there is anything in the buffer, this is not possible; any expression with sizeof is always evaluated at compile-time 1 , it cannot be used to check dynamic things like that. And, again, you cannot use it to compute the size of a block of memory returned by malloc() .
  3. Using strlen() on a buffer holding file data only works reliably if the file is binary and contains a '\\0' in its last position, otherwise you will have an unterminated string and strlen() might invoke undefine behavior.
  4. As I said, you need to check if malloc() returns NULL , which it will do if it fails to allocate the requested block of memory.

1 Except for flexible arrays in C99, but let's ignore that.

99 developers will now answer that you are taking the size of a pointer. I don't even have to look at the code.

The size of a pointer ( char * ) on your (32-bit) platform is always 4.

You can't use sizeof to determine how much memory has been allocated for a buffer.

To check if the pointer has been allocated, check the return value of malloc() :

fileBuff = malloc(size);

if (fileBuff == 0) {
   fprintf(stderr, "Error allocating %d bytes.\n", size);
   abort();
}

sizeof is evaluated at compile time, since you are asking for sizeof of filebuf which is a char* compiler calculates that it is 4 bytes (Since size of the pointer is 4 bytes ub your platform) and prints it. The malloc you did has nothing to do with sizeof .

Apart the improper use of sizeof() you may consider 2 more thoughts:

If it's just to copy a file: Don't try to reinvent the wheel and just use the system() function and call the OS program designed for that ( cp on unix, copy on DOS/Windows).

If it's for training purposes and you therefore insist to do it by yourself: Don't try to read in the whole file and then write it out again, but read and write chunk by chunk. Using to big buffer sizes only results in rendering the CPU cache worthless. Usually matching the file system buffer size or a simple fraction of it is a goot chunk size, so the pseudo code should look like:

open input file for reading
open output file for writing
as long as read from input file BUFSIZE bytes and read bytes > 0
     do write read data to output file
close input file
close output file

(and don't forget to check for I/O errors after each call to an I/O routine!)

And last note: Don't use fgets() unless you know for sure it's a always a plain text file. If you choose to use the fread()/fwrite() you are save, even if it's a binary file (and it's faster, too).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM