【问题标题】:How to populate struct from binary file whilst avoiding issues caused by memory alignment padding?如何从二进制文件填充结构,同时避免内存对齐填充引起的问题?
【发布时间】:2020-11-17 09:05:42
【问题描述】:

我目前正在尝试使用以下代码读取位图文件头:

#include <fstream>
using namespace std;

struct BitMapFileHeader {
    uint16_t bfType;
    uint32_t bfSize;
    uint16_t bfReserved1;
    uint16_t bfReserved2;
    uint32_t bfOffBits;
} file_header;

int main() {
    ifstream fin;
    fin.open("input.bmp", ios::binary);

    fin.read(reinterpret_cast<char*>(&file_header), sizeof(file_header));

}

我文件的前几个字节是42 4D 36 53 07 00 00 00file_header.bfType 显示 19778 的正确值包含在第 1 和第 2 个字节中,但是 filder_header.bfSize 显示 7,它存储在第 5 个字节中,并且似乎跳过了第 3 和第 4 个字节。

看来我遇到了this问题的第二个答案的评论中提到的问题。尽管发现了问题,但我不知道如何解决它。有人能指出我正确的方向吗?

编辑:由于内存访问未对齐的性能问题,有些人不建议打包结构成员。除了一个一个地填充每个结构成员之外,还有什么办法可以避免这种性能损失?

【问题讨论】:

  • 您很可能需要将结构的打包更改为字节对齐。这是使用 #pragma、编译器扩展或某些编译器选项完成的,具体取决于编译器。
  • 您应该提及您正在使用的编译器。
  • @PaulMcKenzie 这是一个将提交给在线评审系统的问题的一部分,编译器和C++标准似乎是随机变化的,所以我无法给出明确的答案。
  • 这不是 C++ 标准问题——它只是一个编译器问题。它取决于如何设置结构对齐方式。 See this。对于 g++,它是使用 __attribute__((packed)) 完成的,对于 Visual C++,它是 #pragma pack(1) 等,以及 pushpop 集合 #pragmas 等。至于你的编辑,这没有任何意义与性能有关。您正在尝试将位图标头“覆盖”到结构上而没有任何失败。
  • @PaulMcKenzie 谢谢。 #pragma pack(1) 工作,所以我假设编译器是 Visual C++

标签: c++ struct binaryfiles memory-alignment


【解决方案1】:

在结构之后使用__attribute__ ((packed))

struct BitMapFileHeader {
    uint16_t bfType;
    uint32_t bfSize;
    uint16_t bfReserved1;
    uint16_t bfReserved2;
    uint32_t bfOffBits;
} __attribute__ ((packed)) file_header;

【讨论】:

  • 如果用户使用与g++ 不同的编译器(例如Visual Studio),这将不起作用。打包结构取决于编译器。
  • 是的。对于vcc,请使用#pragma
【解决方案2】:

问题在于struct 不是字节打包的,因此在成员之间添加了填充。

由于您使用的是Visual C++,因此请使用#pragma packstruct 进行字节打包,同时使用pushpop#pragmas 集将字节打包限制为@987654328 @你有兴趣:

#pragma pack(push)
#pragma pack(1)

struct BitMapFileHeader {
    uint16_t bfType;
    uint32_t bfSize;
    uint16_t bfReserved1;
    uint16_t bfReserved2;
    uint32_t bfOffBits;
} file_header;

#pragma pack(pop)

【讨论】:

    猜你喜欢
    • 2015-04-05
    • 1970-01-01
    • 2011-10-19
    • 2018-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    • 2017-06-08
    相关资源
    最近更新 更多