与对实际文件进行更昂贵的读取相比,我似乎无法将二进制文件加载到内存中以获得更好的读取性能。该文件为124 MB,应该可以完全容纳到内存中。这是C语言,由GCC 6.3在84_64 GNU / Linux上编译。
尝试从blk*
访问fread
时出错。
我尝试过的两个malloc调用是:
uint8_t *blk = malloc(sizeof(uint8_t) * fileSize + 1);
uint8_t *blk = (uint8_t *) malloc(sizeof(uint8_t) * fileSize + 1);
然后检查malloc
是否返回NULL,但没有返回。
FILE *file = fopen("path", "rb");
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
if (ftell(file) != EOF) {
printf("Ftell not EOF);
}
fseek(file, 0, SEEK_SET);
uint8_t *blk = malloc(sizeof(uint8_t) * fileSize + 1);
if (file != NULL) {
printf("File Not NULL and %d\n", fileSize);
}
if (blk) {
printf("Not NULL\n");
} else {
printf("NULL\n");
}
fread(blk, 1, fileSize, file);
fclose(file);
printf("blk: %p | %d\n", *&blk, blk);
输出为:
Ftell not EOF
File Not NULL and 134215964
blk: 0x7fffffffdcc0 | -9024
Not NULL
Segmentation fault
打印格式可能是错误的,但是对于分段错误来说无关紧要。
答案 0 :(得分:2)
如果您还没有弄清楚,您的细分错误是由以下原因引起的:
printf("blk: %p | %d\n", *&blk, blk);
由于尝试将blk
(指向uint8_t
的指针)打印为整数。参数类型和printf
格式说明符之间的不匹配会调用未定义行为。
C11 Standard - 7.21.6.1 The fprintf function(p9)
" If a conversion specification is invalid, the behavior is undefined. If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined."
还请注意,在该语句的'*&'
之前使用blk
是多余的。它就是blk
。取消引用指针的地址只是指针本身。您可以使用blk
中正确的确切宽度宏来更正语句,以打印指针地址和inttypes.h
中的第一个字节,例如
printf("blk: %p | 0x%02" PRIx8 "\n", (void*)blk, *blk);
在您的分配中,无需fileSize + 1
,除非您希望使用hack肯定地 nul-terminate blk
,以便可以将其用作字符串。在某些情况下可能很方便,但是通常不建议这样做。当ftell
返回文件中的字节数时,这就是您需要分配的全部,除非您计划在末尾添加一些内容。此外,像sizeof(uint8_t)
这样的sizeof(char)
总是1
-它也是多余的,例如,
if (!(blk = malloc (filesize))) { /* validate allocation */
perror ("malloc-blk");
return 1;
}
此外,WhozCraig试图向您传达应该验证每个步骤的信息。通过正确的验证,代码在哪里失败就没有任何问题。将验证添加到每个步骤看起来类似于:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
int main (int argc, char **argv) {
uint8_t *blk;
long filesize;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
if (fseek (fp, 0, SEEK_END) == -1) { /* validate seek end */
perror ("fseek-SEEK_END");
return 1;
}
if ((filesize = ftell (fp)) == -1) { /* validate ftell */
perror ("ftell-fp");
return 1;
}
if (fseek (fp, 0, SEEK_SET) == -1) { /* validate seek set */
perror ("fseek-SEEK_SET");
return 1;
}
if (!(blk = malloc (filesize))) { /* validate allocation */
perror ("malloc-blk");
return 1;
}
if (fread (blk, 1, filesize, fp) != (size_t)filesize) { /* validate read */
perror ("fread-blk");
return 1;
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
/* do what you need with blk here */
printf("blk: %p | 0x%02" PRIx8 "\n", (void*)blk, *blk);
free (blk);
}
(注意:使用完成后,请不要忘记free (blk);
)
使用/输出示例
对任何文件按原样运行代码将仅输出blk
的指针地址和文件中的第一个字节(以2进制十六进制表示),例如
$ ./bin/rdfileintoblk ../dat/captnjack.txt
blk: 0x17e9240 | 0x54
仔细研究一下,如果您有任何疑问,请告诉我。