为什么我分配的缓冲区大小不合适?

时间:2012-01-18 20:39:58

标签: c++ file-io

我使用了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 个答案:

答案 0 :(得分:5)

bufferchar*。指针大小为4个字节(对于32位系统)。所以sizeof(buffer)将始终打印4。

分配具有特定大小的指针后,它指向的内存块的大小就是您分配的内存块。在这种情况下,sizeof(char)*fileSize

编辑哦,为了回答你的真正的问题,在Windows中没有问题,其中ftell以字节为单位报告大小,将每个CRLF计为2个字节。当您在缓冲区中读取此内容时,CRLF将转换为单字节\n,从而减​​小结果文本的大小。
(现在不在Windows上,无法检查。)

答案 1 :(得分:3)

正确分配缓冲区。缓冲区大小使用sizeof(char)*fileSize计算,而不是sizeof(buffer)。您可以通过验证buffer是否为空来测试缓冲区是否已分配。如果不是,那么它成功地分配了大小大于或等于您请求的大小的缓冲区。

问题是您以文本模式打开了文件。因此,Windows将用ANSI C要求的“\ n”替换文件中的所有“\ r \ n”序列。您可以接受此行为,也可以使用fp = fopen("help.txt","rb");以二进制模式打开文件以读取所有未更改的内容。

答案 2 :(得分:2)

虽然您可以投射malloc(对于C ++)的结果,但您不需要乘以sizeof(char) always one。< / p>

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个字节。