将二进制文件读取到结构中,还有endianness问题



我想将二进制文件image.dd读入struct teststruct *test;。基本上有两个问题:


1.由于小/大端序,顺序错误

printf("%02x", test->magic);只是给了我534b554c而不是4c55b453(也许这与下一部分的"主要问题"有关(。它只是";一个值";。例如,printf("%c", test->magic);给出了L而不是LUKS


2.test->version无输出

CCD_ 11中的CCD_。这意味着,我调用printf("%x ", test->version);,但没有结果。


这是包含struct:的exampleh.h

#ifndef _EXAMPLEH_H
#define _EXAMPLEH_H
#define MAGIC_L     6
struct teststruct {
char                magic [MAGIC_L];
uint16_t            version;
};
#endif

这是main代码:

using namespace std;
#include <stdint.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include "exampleh.h"
struct teststruct *test;
int main() {
FILE *fp = fopen("C:\image.dd", "rb");     // open file in binary mode
if (fp == NULL) {
fprintf(stderr, "Can't read file");
return 0;
}
fread(&test,sizeof(test),1,fp);
//printf("%x ", test->magic);   //this works, but in the wrong order because of little/big endian
printf("%x ", test->version);   //no output at all
fclose(fp);
return 0;
}

这是image.dd:的前114个字节

4C 55 4B 53 BA BE 00 01 61 65 73 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 78 74 73 2D 70 6C 61 69 
6E 36 34 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 73 68 61 32 35 36 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 10 00 00 00 00 40
  • 您必须分配结构并将数据读取到结构中,而不是直接读取指针。如果只读取一个结构,则不需要为该结构声明指针
  • printf("%x ", test->magic);调用未定义的行为,因为指针(从数组自动转换而来(被传递到需要unsigned int的位置

在这种情况下,观察到的行为是因为:

首先,fread(&test,sizeof(test),1,fp);从文件中读取前几个字节作为指针值。

然后,printf("%02x", test->magic);打印文件中的第一个4字节整数,因为test->magic是(转换为(指向位于结构顶部的数组的指针,并且数组的地址与结构本身的地址相同,因此打印从文件中读取的地址。另一个幸运的是,从哪里读取4字节整数和地址(指针(作为函数参数是相同的。

最后,您并没有从printf("%x ", test->version);获得任何输出,因为从文件中读取的地址不幸地位于不可读的区域中,并且试图读取该区域会导致Segmentation Fault。

固定代码:

using namespace std;
#include <stdint.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include "exampleh.h"
struct teststruct test; // allocate structure directly instead of pointer
int main() {
FILE *fp = fopen("C:\image.dd", "rb");     // open file in binary mode
if (fp == NULL) {
fprintf(stderr, "Can't read file");
return 0;
}
fread(&test,sizeof(test),1,fp); // now structure is read instead of pointer
for (int i = 0; i < 6; i++) {
printf("%02x", (unsigned char)test.magic[i]); // print using proper combination of format and data
}
printf(" ");
printf("%x ", test.version); // also use . instead of ->
fclose(fp);
return 0;
}

struct teststruct *test;指向NULL,因为它是在全局命名空间中定义的。您没有为此指针分配内存,因此test->version是UB。

fread(&test,sizeof(test),1,fp);也是错误的,这将读取指针,而不是结构的内容。

一个简单的解决方案是将test更改为struct teststruct,而不是指向它的指针

using namespace std;
#include <stdint.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include "exampleh.h"
struct teststruct test; //not a pointer anymore
int main() {
FILE *fp = fopen("C:\image.dd", "rb");     // open file in binary mode
if (fp == NULL) {
fprintf(stderr, "Can't read file");
return 0;
}
fread(&test,sizeof(test),1,fp);
//printf("%x ", test.magic);   //this works, but in the wrong order because of little/big endian
printf("%x ", test.version);   //no output at all
fclose(fp);
return 0;
}

相关内容