如何解决Linux下C++结构体扩展时的柔性数组非末尾成员错误
问题:Linux进程变更检测结构体编译错误及优化方案咨询
背景
我曾使用如下结构体处理Linux进程变更检测:
struct __attribute__((aligned(NLMSG_ALIGNTO))) event_message { nlmsghdr f_nl_hdr; struct __attribute__((__packed__)) { cn_msg f_cn_msg; proc_event f_proc_ev; } f_nl_msg; };
编译错误
升级至Ubuntu 23.04的g++12.2.0后,触发编译错误:
/usr/include/linux/connector.h: In member function ‘void ed::process_changed::listen_for_events()’: /usr/include/linux/connector.h:78:14: error: flexible array member ‘cn_msg::data’ not at end of ‘struct ed::process_changed::listen_for_events()::multicast_message’ 78 | __u8 data[]; | ^~~~
错误原因是cn_msg中的柔性数组成员data[]并非所在嵌套结构体的最后成员,旧编译器可正常编译,但新编译器直接报错;且我开启了-Werror将警告视为错误,无法通过#pragma忽略该错误。
已尝试的解决方案
我想到通过手动分配内存并强制转换的方式规避问题,步骤如下:
- 计算所需总内存大小:
constexpr std::size_t size(sizeof(nlmsghdr) + sizeof(cn_msg) + sizeof(proc_event));
- 创建字节缓冲区:
std::vector<std::uint8_t> buffer(size);
- 将缓冲区转换为对应结构体指针:
nlmsghdr * header = reinterpret_cast<nlmsghdr *>(buffer.data()); cn_msg * msg = reinterpret_cast<cn_msg *>(header + 1); proc_event * event = reinterpret_cast<proc_event *>(msg + 1);
*注:查阅reinterpret_cast文档后,我认为该操作不属于未定义行为,前提是各结构体的对齐要求一致,且缓冲区对应位置的字节符合目标结构体格式。
但此方案代码繁琐且容易出错,希望找到更简洁可靠的替代方案。
约束条件
- 必须使用
/usr/include下的系统头文件定义,不能自行重定义结构体,以适配当前系统版本 - 代码仅需支持Ubuntu平台下的g++编译,无需考虑其他平台兼容性
内容的提问来源于stack exchange,提问作者Alexis Wilke
相关产品推荐
相关产品推荐

