C++标准定义的对象能否持久化到内存映射文件及跨进程共享内存?
跨存储/进程访问二进制序列化对象的C++标准合规性解答
核心判定规则
C标准中,一个对象可以被合法访问的核心前提是其生存期已正确启动,仅靠二进制内容和对象表示完全匹配,不足以证明访问行为合法。C20版本新增了隐式对象创建规则,和旧版本标准的判定逻辑有明显差异。
场景1:内存映射文件跨程序访问
- C17及更早版本标准:完全不符合规范,属于未定义行为。旧标准没有隐式对象创建规则,程序2映射文件得到的内存区域中,从未执行过任何对象创建操作(没有定义语句、没有
new调用、没有显式构造函数调用),该区域内不存在任何合法C对象,直接用reinterpret_cast转换为对象指针访问的行为完全非法。 - C20及更新版本标准:仅当访问的对象属于隐式生存期类型(平凡类型、标量类型、上述类型的数组,即没有非平凡构造/析构函数、没有虚函数的类型)时符合规范。C20规定,当存储区域内已经写入符合某隐式生存期类型对象表示的二进制内容时,首次访问该存储时会隐式创建对应的合法对象,此时
reinterpret_cast访问的行为是合法的。如果访问的是非隐式生存期类型,仍然属于未定义行为。
场景2:进程共享内存跨进程访问
该场景的判定规则和内存映射文件完全一致:
- C++17及更早版本标准:无论访问任何类型都属于未定义行为。
- C++20及更新版本标准:仅访问隐式生存期类型时符合规范,非隐式生存期类型访问非法。
额外注意事项
即使符合标准合规要求,实际使用时仍需要保证两个进程/程序使用完全一致的编译选项、ABI约定,避免同一类型的对象内存布局、二进制表示出现差异,导致实际运行出错。本判定不涉及共享本地虚拟地址的场景,该类操作的风险已属于公认范畴。
内容的提问来源于stack exchange,提问作者Richard Critten
相关产品推荐
相关产品推荐

