我正在使用下面的代码在
Windows上的MSVC中打开一个大的(5.1GB)二进制文件.机器有大量的RAM.问题是长度被检索为零.但是,当我将file_path更改为较小的ASCII文件时,代码工作正常.
为什么我不能加载大二进制文件?我喜欢这种方法,因为我想要一个指向文件内容的指针.
FILE * pFile; uint64_t lSize; char * buffer; size_t result; pFile = fopen(file_path,"rb"); if (pFile == NULL) { fputs("File error",stderr); exit(1); } // obtain file size: fseek(pFile,SEEK_END); lSize = ftell(pFile); // RETURNS ZERO rewind(pFile); // allocate memory to contain the whole file: buffer = (char*)malloc(sizeof(char)*lSize); if (buffer == NULL) { fputs("Memory error",stderr); exit(2); } // copy the file into the buffer: result = fread(buffer,1,lSize,pFile); // RETURNS ZERO TOO if (result != lSize) { // THIS FAILS fputs("Reading error",stderr); exit(3); } /* the whole file is now loaded in the memory buffer. */
它不是文件的权限或任何东西,他们是罚款.
解决方法
如果您分配了5,1 GB,最好确保您已经编译了64位的代码,并在64位Windows版本上运行. Ohterwhise,内存
address space is limited到最大3 GB,32位Windows和
4 GB with 32 bits code on a 64 bits Windows.
顺便说一下,ftell()
返回一个签名的长.您必须检查这里是否有错误(例如,如果操作系统允许较大的文件大小,则会出现溢出),以使该值不为-1.
编辑:
请注意,with MSVC,long
will currently be即使编译为64位也是32位数.这意味着如果文件大小在2GB以下(因为符号),ftell()会给你一个有意义的结果.
您可以使用非便携式操作系统特定的WinAPI功能GetFileSizeEx()
来获取带有64位数的大型文件的大小.
malloc()需要一个size_t,这是一个unsigned 64 bit number.所以在这方面你是安全的.
另一种方法是使用file mapping.
第二编辑
我看着你对大小收到的价值的编辑,这与我预期的不一样.我可以在我的系统上重现错误,并且具有不为空的大小,但它比文件大得多.
从this CERT security recommendation看,fseek()与SEEK_END相结合的标准提供的担保是不合适的,这使得这是一个非常不安全的做法.
所以让我们重申一下:获取大小的最简单的方法是在Windows上使用本机OS功能,即GetFileSizeEx().在64位窗口中有一个解决方法:使用_fseeki64()和_ftelli64():
... if (_fseeki64(pFile,SEEK_END)) { fputs("File seek error",stderr); return (1); } lSize = _ftelli64(pFile); // RETURNS EXACT SIZE ...
这一点很好(初始问题似乎与不够大的返回类型相关联).但是请记住,这是一个解决方法,我担心可能会有其他错误条件可能导致CERT报告的漏洞.