【发布时间】:2019-10-03 05:51:17
【问题描述】:
与读取实际文件的成本更高相比,我似乎无法将二进制文件加载到内存中以获得更好的读取性能。该文件为 124 MB,应该能够完全放入内存中。这是 C 语言,由 GCC 6.3 在 84_64 GNU/Linux 上编译。
尝试从fread 访问blk* 时出现问题。
我尝试的两个 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
打印格式可能有误,但不会影响分段错误。
【问题讨论】:
-
您可以比这更深入地检测它。比如,检查
fopen是否成功。检查fseeks 是否成功;ftell没有返回 EOF(通常为 -1,想想 that 对你的那个小尺寸方程做了什么)。永远不要假设 IO 有效。假设是一切之母...... -
GCC 没有给出关于
uint8_t blk*的警告或错误? -
所有其他部分都可以工作,我很确定错误出现在 malloc 或 fread 行@WhozCraig
-
我提到的绝对什么都没有。此代码中有六个错误点,实际上只有一个错误点被检测(即使在功能上也没有考虑到这一点;如果在报告同样多的情况下
blk为 NULL,则代码会进入未定义的行为)。需要调试器和/或更好的工具,最好是前者,但如果覆盖范围很广,后者就足够了。 -
除了
fread(blk, 1, 1, file);只从file读取一个字节到blk。远远少于fileSize + 1字节...另外,鉴于您的不确定性,没有必要强制返回malloc,这是不必要的。见:Do I cast the result of malloc?请同时输出ls -al path的结果。
标签: c gcc segmentation-fault malloc fread