【问题标题】:Strange behavior: same code on different locations, one fails reading binary file奇怪的行为:不同位置的相同代码,一个无法读取二进制文件
【发布时间】:2011-08-13 20:56:10
【问题描述】:

我在处理一小段代码时遇到问题,我正在尝试读取二进制文件,如果我在单独的文件中有此代码,构建并运行它,它会完美读取文件,但如果我把函数中较大项目上的相同代码,它总是错误地读取数据(对于 2 个测试是同一个文件)。

这是单独项目上的代码:

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

int main(int argc, char* argv[]) {
    char* filename = (char*)"file.binary";
    FILE* file = fopen(filename, "rb");

    if (!file) {
        printf("Unable to open %s for reading. \n", filename);
        fclose(file);
        free(filename);
        exit(1);
    }

    fseek (file , 0 , SEEK_END);
    long size = ftell (file);
    rewind (file);

    printf("Number of bytes in the file is %ld \n", size);

    int version = 0;

    char* string = (char*)malloc(sizeof(char) * 3);
    fread(string, sizeof(char), 3, file);

    if (strcmp(string, (char*)"str")) {
        printf("%s is not properly formatted. \n", filename);
        fclose(file);
        free(filename);
        exit(1);
    }

    fread(&version, sizeof(int), 1, file);

    printf("%s version %d\n", string, version);

    free(filename);
    fclose(file);
}

我不会在更大的项目上发布代码,因为它完全相同(复制粘贴),除了因为它位于类函数内部而不是直接在主函数上。这是一段相当简单的代码,但由于某种奇怪的原因它失败了,我无法理解它。两种情况下都正确读取文件大小,单独的项目正确读取“字符串”和“版本”数据并正确打印它,但是在较大的项目中它总是进入第二个条件,因为字符串不是预计会是什么。

我不认为这是相关的,但更大的项目正在构建到一个静态库中,该库稍后用于从主程序链接。

有人知道我可能会失踪吗?谢谢。

【问题讨论】:

  • 所有的选角狂热是怎么回事?请将char* filename = (char*)"file.binary"; 替换为const char* filename = "file.binary";,并且不要转换malloc() 的结果。最后,我对 string 只有 3 个字节长而不以零结尾但与 4 个字节的字符串进行比较感到不舒服。
  • 当 OP 提到“类函数”时,我猜他提到的更大程序的上下文是 C++,而不是 C。
  • 是的,较大程序的上下文是 C++。强制转换是因为 g++ 抱怨 void* 和 char* 不是同一种数据类型。至于使用 const char* 作为数据类型,在较大的项目中实际上不是一个选项,因为文件名将被修改。

标签: c file binary


【解决方案1】:
char* string = (char*)malloc(sizeof(char) * 3);
fread(string, sizeof(char), 3, file);
if (strcmp(string, (char*)"str")) {
}

您为三个字符分配内存,但您与四个字符进行比较:“str”和空字节。您应该分配四个字节并将最后一个字节设置为零(或简单地使用calloc)。我可以想象第四个字节在独立应用程序中确实是零,但在更大的项目中却不是。

【讨论】:

  • 就是这样,第 4 字节在较大的项目中被弄乱了,但我没有注意到,因为在单独的项目中它工作正常。我必须更加小心空终止:-/。谢谢你:-)。
  • strncmp 函数也可用于避免 \0 问题。响应“不同位置”,如果您正在跨不同类型的架构(x86 与 PowerPC、SPARC、...)进行编译,那么如果整数值读取不正确,您可能还会遇到大端与小端的问题。
  • 我不知道 strncmp,感谢您的提示,它在某些情况下可能会很有用,尽管在这种情况下,如果我习惯于对这些 char* 进行空终止,它似乎更安全。字节序目前不是问题,因为所有目标架构都使用小字节序,但既然您提到它,可能值得在某处添加注释,以防此代码用于大字节序架构并需要未来扩展。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-12
  • 2018-03-14
  • 1970-01-01
  • 1970-01-01
  • 2013-10-17
  • 1970-01-01
相关资源
最近更新 更多