Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create and use a stack-allocated struct ending with a C99 flexible array member in C++ without undefined behaviour?

I'm calling a 3rd-party C99 library from modern C++. The API contains a struct that ends with a flexible array member. To allocate the struct on the stack I think I need a byte buffer then cast it to the struct.

Is my use of reinterpret_cast well-defined (i.e., is not undefined behavior)?

#include <cstddef>
#include <print>

// 3rd-part C99 API
extern "C" {
  struct Foo {
    int length;
    int array[];
  };

  void do_something(struct Foo*);
}

// My C++ code
auto bar() {
  auto length = 4;
  std::byte buffer[sizeof(Foo) + length * sizeof(int)];
  auto &foo = *reinterpret_cast<Foo *>(buffer); // ← Is this UB?
  foo.length = length;
  do_something(&foo); // ← Is this UB?
  std::println("Result: {}", foo.array[3]); // ← Is this UB?
}

Edit: I'm compiling with -std=gnu++23 so flexible array members will compile.

like image 659
Peter Sutton Avatar asked Oct 16 '25 14:10

Peter Sutton


1 Answers

IMO it is UB. But you can do something like this (VLAs are not portable in C++ and it is gcc-centric):

#include <cstddef>
#include <new>
#include <print>

extern "C" {
  struct Foo {
    int length;
    int array[]; // non-portable C++ extension
  };
  void do_something(struct Foo*);
}

auto bar() {
  int length = 4;

  // Ensure proper alignment for Foo
  alignas(Foo) std::byte storage[sizeof(Foo) + length * sizeof(int)];

  // Create a Foo object in that storage
  auto* foo = std::construct_at(reinterpret_cast<Foo*>(storage));
  foo->length = length;               // initialize header before calling C

  do_something(foo);                  // now OK (alignment + lifetime are fine)

  // OK if do_something wrote at least 4 ints
  std::println("Result: {}", foo->array[3]);

  std::destroy_at(foo);               // trivial, but symmetric
}

https://godbolt.org/z/Kr5zxfqWj

like image 167
0___________ Avatar answered Oct 18 '25 11:10

0___________



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!