Почему мой выделенный буфер имеет неправильный размер? - PullRequest
0 голосов
/ 19 января 2012

Я использовал функцию fread и получаю размер буфера 4 и «Ошибка чтения».

Почему мой buffer не fileSize?

код:

FILE *fp;
char* buffer;
fp = fopen("help.txt","r");
if (fp == NULL){
    fputs("Can't open Help file, Help.txt",stderr);
exit(1);
}
fseek(fp, 0, SEEK_END);
long fileSize = ftell(fp);
rewind(fp);

buffer = (char*) malloc (sizeof(char)*fileSize);
if(buffer == NULL){
    fputs("Memory Allocation Error",stderr);
    exit(2);
}

size_t result = fread(buffer,1,fileSize,fp);
if(result != fileSize){
fputs("Reading error\n",stderr);
printf("File Size : %lu\n",fileSize);
printf("Result : %lu\n",result);
printf("Buffer Size : %u\n",sizeof(buffer));
exit(3);
}

fputs(buffer,stdout);

fclose(fp);
free (buffer);

Это вывод при запуске программы:

Reading error
File Size : 224
Result : 219
Buffer Size : 4

Ответы [ 3 ]

5 голосов
/ 19 января 2012

buffer является char*. Указатели имеют размер 4 байта (для 32-битной системы). Так что sizeof(buffer) всегда будет печатать 4.

После того, как вы выделите указатель с определенным размером, размер блока памяти, на который он указывает, соответствует тому, с чем вы его выделили. В этом случае sizeof(char)*fileSize.

Edit О, чтобы ответить на ваш real вопрос, не было ли проблемы в Windows, где ftell сообщает размер в байтах, считая каждый CRLF как 2 байта. Когда вы читаете это в буфере, CRLF переводятся в один байт \n s, уменьшая размер получаемого текста.
(Сейчас нет в Windows, не могу проверить.)

3 голосов
/ 19 января 2012

Буфер размещен правильно.Размер буфера рассчитывается с использованием sizeof(char)*fileSize, а не sizeof(buffer).Вы можете проверить, был ли буфер выделен или нет, проверив, является ли buffer нулевым.Если это не так, он успешно выделил буфер с размером, большим или равным запрошенному вами размеру.

Проблема в том, что вы открыли файл в текстовом режиме.По этой причине Windows заменит все последовательности «\ r \ n» в вашем файле на «\ n», как того требует ANSI C.Вы можете принять это поведение или открыть свой файл в двоичном режиме, используя fp = fopen("help.txt","rb");, чтобы прочитать все содержимое без изменений.

2 голосов
/ 19 января 2012

Пока все в порядке, приведя результат malloc (для C ++), вам не нужно умножать на sizeof(char), то есть всегда one .

Функция sizeof не возвращает количество байтов, выделенных для переменной, выделяемой во время выполнения (которую вы уже храните в fileSize). Это работает только так, как вы ожидаете от статически распределенных переменных (например, int foo[BAR]; /* sizeof(foo) returns sizeof(int)*BAR bytes */).

#include <stdlib.h>
#include <stdio.h>

#define BAR 10

int main() {
    int foo[BAR];
    int *baz;

    fprintf(stdout, "foo: %zu\n", sizeof(foo)); /* 40 */

    baz = malloc(sizeof(int) * BAR);
    if (baz != NULL) {
        fprintf(stdout, "baz: %zu\n", sizeof(baz)); /* not 40, but sizeof(int*) */
        free(baz);
    }
    else {
        fprintf(stdout, "could not allocate memory for baz\n");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

$ gcc -Wall -o test test.c
$ ./test
foo: 40
baz: 8

В 64-битной системе указатель составляет 8 байтов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...