How to align capnproto data to architectures word size?

159 views
Skip to first unread message

SR D

unread,
Jul 16, 2021, 3:39:08 PM7/16/21
to Cap'n Proto
I am trying to reconstruct received data using Capnproto, but am getting the following error.

    terminate called after throwing an instance of 'kj::ExceptionImpl'
      what():  capnp/arena.c++:76: failed: expected reinterpret_cast<uintptr_t>(segment.begin()) % sizeof(void*) == 0 [4 == 0]; Detected unaligned data in Cap'n Proto message. Messages must be aligned to the architecture's word size. Yes, even on x86: Unaligned access is undefined behavior under the C/C++ language standard, and compilers can and do assume alignment for the purpose of optimizations. Unaligned access may lead to crashes or subtle corruption. For example, GCC will use SIMD instructions in optimizations, and those instrsuctions require alignment. If you really insist on taking your changes with unaligned data, compile the Cap'n Proto library with -DCAPNP_ALLOW_UNALIGNED to remove this check.
    stack: 7f4233c40ca5 7f423bbc40cf6 7f42bbccaa27 55f370c02321 55f770cc18e3 55f77ac01331 55f77a0b12da 55f7a0cb127b 55fc70c0d1ed 55fe70c01137 7f42bffa7de3 7f42b5cc7608 7f42b5aa6292


It is from this snippet where I am receiving the buffer and trying to rebuild the data structure.

    const void* buff = getBuff();
    
    auto arr = kj::ArrayPtr<const capnp::word>(
        reinterpret_cast<const capnp::word*>(buff),
        size / sizeof(capnp::word));

    capnp::FlatArrayMessageReader msgReader(arr);

    auto msg = msgReader.getRoot<MyStuff>(); // error occurs at this line
    auto fieldA = msg.getFieldA();
    auto fieldB = msg.getFieldB();

    

The buffer was constructed and sent using:

    capnp::MallocMessageBuilder message;
    auto stuff = message.initRoot<MyStuff>();
    stuff.setFieldA("A");
    stuff.setFieldB("B");
    
    const auto msgToSend = capnp::messageToFlatArray(message);
    const auto msgAsChars = msgToSend.asChars();

    // make const void* and send

How do I align the data to the architectures word size as the error says?

Kenton Varda

unread,
Jul 17, 2021, 11:04:01 AM7/17/21
to SR D, Cap'n Proto
Ideally, you'd update the implementation of `getBuff()` so that it allocates an aligned buffer. Note that malloc() always returns aligned buffers, so if you can make it so that the pointer returned by getBuff() is one that was allocated directly by malloc(), then it should work. Probably, though, getBuff() is returning a pointer into some larger buffer that was read off the wire, including some framing bytes that are pushing the data out of alignment. In this case it may be impractical to get the data to come out aligned, so you may have no choice but to make a copy. You can do something like:

auto copy = kj::heapArray<capnp::word>(size / sizeof(capnp::word));
memcpy(copy.begin(), buff, size);

The copy will then be aligned.

-Kenton

--
You received this message because you are subscribed to the Google Groups "Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email to capnproto+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/capnproto/c6755765-f1f3-4de6-af29-dfdb2bb83881n%40googlegroups.com.

SR D

unread,
Jul 17, 2021, 12:55:41 PM7/17/21
to Cap'n Proto
Thank you.
Reply all
Reply to author
Forward
0 new messages