我读取一个文件,将数据放入缓冲区,比如说
char array
。之后,我将部分数据复制到结构体并增加偏移量以读取下一个数据部分。该结构体就像一个标头,其成员int dataSize
可以指示其后面的数据加载的可变大小。
缓冲区可以像这样可视化:
| headerA |
| dataLoad |
| dataLoad |
| dataLoad |
| headerB |
| dataLoad |
| dataLoad |
发生了一些事情,可能是由于数据未对齐,并且发生了 SIGBUS。我想问在访问之前使用align重新对齐数据是否很常见
header
?
这是我的简单程序来说明情况:
#include <iostream>
#include <cstring>
#include <cstdint>
#include <memory>
using namespace std;
typedef struct HeaderA {
int dataSize;
char y;
int z;
} HeaderA; // 12 bytes after padding by compiler
typedef struct HeaderB{
char x;
int dataSize;
char z;
} HeaderB; // 12 bytes after padding by compiler
void copyHeaderA(HeaderA& dest, const char* src) {
memcpy(&dest, src, sizeof(HeaderA));
}
void copyHeaderB(HeaderB& dest, const char* src) {
memcpy(&dest, src, sizeof(HeaderB));
}
int main() {
char data[100]; // 100 bytes
HeaderA headerA;
int offset = 1; // intentionally put offset = 1 to cause mis-alignment when reading dataSize at HeaderA
if (offset + sizeof(HeaderA) <= sizeof(data)) {
copyHeaderA(headerA, &data[offset]);
offset += (sizeof(HeaderA) + headerA.dataSize);
}
HeaderB headerB;
if (offset + sizeof(HeaderB) <= sizeof(data)) {
copyHeaderB(headerB, &data[offset]);
offset += (sizeof(HeaderB) + headerB.dataSize);
}
return 0;
}
我的解决方法是调用
std::align
来“重新对齐”dataSrc。您觉得这个修复怎么样?另外,如果你知道如何调试,并显示内存地址,请帮助我。
#include <iostream>
#include <cstring>
#include <cstdint>
#include <memory>
using namespace std;
typedef struct HeaderA {
int dataSize;
char y;
int z;
} HeaderA; // 12 bytes after padding
typedef struct HeaderB{
char x;
int dataSize;
char z;
} HeaderB; // 12 bytes after padding
void copyHeaderA(HeaderA& dest, const char* src) {
memcpy(&dest, src, sizeof(HeaderA));
}
void copyHeaderB(HeaderB& dest, const char* src) {
memcpy(&dest, src, sizeof(HeaderB));
}
int main() {
char data[100]; // 100 bytes
HeaderA headerA;
int offset = 1;
if (offset + sizeof(HeaderA) <= sizeof(data)) {
const char* alignedPtrA = &data[offset];
std::size_t spaceA = sizeof(data) - offset;
if (std::align(alignof(HeaderA), sizeof(HeaderA), (void*&)alignedPtrA, spaceA)) {
copyHeaderA(headerA, alignedPtrA); // Ensure alignment before copying
offset += sizeof(HeaderA);
} else {
std::cerr << "Alignment failed for HeaderA" << std::endl;
}
}
HeaderB headerB;
if (offset + sizeof(HeaderB) <= sizeof(data)) {
const char* alignedPtrB = data + offset;
std::size_t spaceB = sizeof(data) - offset;
if (std::align(alignof(HeaderB), sizeof(HeaderB), (void*&)alignedPtrB, spaceB)) {
copyHeaderB(headerB, alignedPtrB); // Ensure alignment before copying
offset += sizeof(HeaderB);
} else {
std::cout << "Alignment failed for HeaderB" << std::endl;
}
}
return 0;
}
std::align
用于标识缓冲区内充分对齐的区域,该区域本身未对齐(因为它不是指定类型的缓冲区)。由于您已将 headerA
和 headerB
声明为局部变量,因此它们已经充分对齐。