0

I read a file, put the data into a buffer, say char array. After that I copy part of the data to a struct and increment an offset to read the next data part. The struct is like a header, whose member int dataSize can indicate the variable size of the data load following it.

The buffer could be visualized like this:

| headerA    |
| dataLoad   |
| dataLoad   |
| dataLoad   |
| headerB    |
| dataLoad   |
| dataLoad   |

Something happens, possibly due to misaligned data, and SIGBUS occurs. Is it common to use align to realign data before accessing header?

Here is my simple program to illustrate the situation:

#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;
}

My fix is to call std::align to "re-align" the dataSrc. What do you think of this fix? I am also interested to learn how to debug and show the memory address.

#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, suppose that this is read from a file and is valid. 
    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;
}
1
  • 1
    In the first code snippet you're copying uninitialized bytes into a HeaderA and then using the HeaderA::dataSize field: that's undefined behaviour. Commented Oct 24, 2024 at 10:06

1 Answer 1

0

std::align is used to identify a sufficiently aligned region within a buffer which is not itself aligned (because it was not a buffer of the specified type). Since you've declared headerA and headerB as local variables, they're already sufficiently aligned.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.