使用 std::align 函数修复由于数据未对齐而导致的 SIGBUS 潜在问题

问题描述 投票:0回答:1

我读取一个文件,将数据放入缓冲区,比如说

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;
}
c++ memory-alignment
1个回答
0
投票

std::align
用于标识缓冲区内充分对齐的区域,该区域本身未对齐(因为它不是指定类型的缓冲区)。由于您已将
headerA
headerB
声明为局部变量,因此它们已经充分对齐。

© www.soinside.com 2019 - 2024. All rights reserved.