Malloc - размер базы файлового буфера в существующем файле.

В моем проекте мне нужно скопировать общий файл в каталог, который называется share. Моя идея - скопировать содержимое этого файла с помощью fgets и 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!!

Однако файловый буфер не может быть перераспределен, размер этого файлового буфера всегда равен 4. что происходит?

обновление: похоже есть какое-то недоразумение. sizeof (), если я просто хочу проверить, хранится ли что-нибудь в файловом буфере. Я пробую strlen (fileBuff), и он всегда дает мне 1.


person panda    schedule 13.04.2012    source источник
comment
Лучше использовать fstat, чтобы найти размер файла, чем искать до конца и т. Д.   -  person Ed Heal    schedule 13.04.2012


Ответы (5)


Это неправильно: sizeof(fileBuff). Это будет размер указателя, который в вашей системе равен 4.

Вы не можете использовать sizeof для «извлечения» размера блока памяти, возвращаемого malloc(). Вы не можете использовать что-нибудь для извлечения этого размера, это просто невозможно в (стандартном) C. Вам нужно использовать значение size, то есть аргумент для malloc().

Кроме того, ftell() возвращает long, а не int, и как malloc(), так и различные вызовы ввода-вывода могут завершиться ошибкой, что вам необходимо принять во внимание.

На мой взгляд, использовать буфер размером с файл для простого копирования - не лучшая идея; Намного лучше использовать «разумный» буфер (точный оптимальный размер которого зависит от множества факторов), а затем повторять пары чтения-записи в цикле, пока вы не пройдете через весь файл.

ОБНОВЛЕНИЕ Дополнительные сведения о вашем коде:

  1. Вы говорите об использовании strlen(), но в коде также отображается sizeof после fread().
  2. Вы говорите об использовании sizeof для «проверки», есть ли что-нибудь в буфере, это невозможно; любое выражение с sizeof всегда оценивается во время компиляции 1, его нельзя использовать для проверки подобных динамических вещей. И, опять же, вы не можете использовать его для вычисления размера блока памяти, возвращаемого malloc().
  3. Использование strlen() в буфере, содержащем данные файла, работает надежно только в том случае, если файл является двоичным и содержит '\ 0' в последней позиции, иначе у вас будет незавершенная строка, и strlen() может вызвать поведение undefine.
  4. Как я уже сказал, вам нужно проверить, возвращает ли malloc() NULL, что он и сделает, если не сможет выделить запрошенный блок памяти.

1 За исключением гибких массивов в C99, но давайте проигнорируем это .

person unwind    schedule 13.04.2012
comment
Большое спасибо, но почему я могу заблокировать файловый буфер? только из-за типа данных? программа не сообщает об ошибках, но в файловый буфер ничего не помещается. Это просто не может быть искажено - person panda; 13.04.2012

99 разработчиков теперь ответят, что вы берете размер указателя. Мне даже не нужно смотреть на код.

person Martin James    schedule 13.04.2012
comment
+1 Ха-ха, я подумал то же самое после прочтения вопроса (однако я действительно просмотрел код, чтобы подтвердить свою гипотезу). ;-) - person Frerich Raabe; 13.04.2012
comment
это тестовый код, я пытаюсь использовать strlen (fileBuff), но он возвращает 1. И sizeof (), и strlen предназначены для проверки того, был ли неправильно размещен файловый буфер. - person panda; 13.04.2012

Размер указателя (char *) на вашей (32-битной) платформе всегда равен 4.

Вы не можете использовать sizeof, чтобы определить, сколько памяти было выделено для буфера.

Чтобы проверить, был ли назначен указатель, проверьте возвращаемое значение malloc():

fileBuff = malloc(size);

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

sizeof оценивается во время компиляции, поскольку вы запрашиваете sizeof из filebuf, который является char* компилятором, вычисляет, что это 4 байта (поскольку размер указателя составляет 4 байта на вашей платформе), и печатает его. malloc, который вы сделали, не имеет ничего общего с sizeof.

person Asha    schedule 13.04.2012

Помимо неправильного использования sizeof (), вы можете подумать еще о двух мыслях:

Если это просто копирование файла: не пытайтесь изобретать велосипед, просто используйте функцию system () и вызовите программу ОС, предназначенную для этого (cp в unix , копировать в DOS / Windows).

Если это в целях обучения, и поэтому вы настаиваете на том, чтобы сделать это самостоятельно: не пытайтесь прочитать файл целиком, а затем записать его снова, а читать и записывать фрагмент за фрагментом. Использование буфера больших размеров приводит только к тому, что кеш-память ЦП становится бесполезной. Обычно размер буфера файловой системы или его простая часть соответствует размеру блока goot, поэтому псевдокод должен выглядеть так:

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

(и не забывайте проверять ошибки ввода-вывода после каждого вызова подпрограммы ввода-вывода!)

И последнее замечание: не используйте fgets (), если вы не знаете наверняка, что это всегда простой текстовый файл. Если вы решите использовать fread () / fwrite (), вы сохраните, даже если это двоичный файл (и он быстрее).

person ktf    schedule 13.04.2012