C++ 在不违反严格别名规则的情况下访问进程间共享内存中的对象

C++ 在不违反严格别名规则的情况下访问进程间共享内存中的对象,c++,ipc,c++17,shared-memory,interprocess,C++,Ipc,C++17,Shared Memory,Interprocess,我有多个用C++17编写的程序,运行在Linux上 一个程序在/dev/shm/下创建一个文件,并将其映射到内存空间。然后,它继续使用placement new初始化共享内存中的POD对象 其他进程将打开这些文件并将其映射到其内存空间以访问对象。目前,我使用的是C风格的CAST,它工作,但我相信它是技术上未定义的行为,每一个C++别名规则,所以这可能会在未来版本的GCC。 编译器不知道该内存位置存在对象。通常,我会通过调用placement new将其传递给编译器,但在本例中,这将在现有对象上初

我有多个用C++17编写的程序,运行在Linux上

一个程序在/dev/shm/下创建一个文件,并将其映射到内存空间。然后,它继续使用placement new初始化共享内存中的POD对象

其他进程将打开这些文件并将其映射到其内存空间以访问对象。目前,我使用的是C风格的CAST,它工作,但我相信它是技术上未定义的行为,每一个C++别名规则,所以这可能会在未来版本的GCC。 编译器不知道该内存位置存在对象。通常,我会通过调用placement new将其传递给编译器,但在本例中,这将在现有对象上初始化(我认为这也是未定义的行为)

我应该如何访问此对象而不违反严格的别名规则?
这是一个使用案例吗?

mmap函数返回一个void指针,严格的类型别名规则不适用于void指针,因为它们不指向实际的类型,但需要在访问之前强制转换到某个类型。在C++中,在空指针上使用C类强制转换或更好的静态转换是完全合法的。
但如果您访问共享内存中的数据,这可能会成为一个优化问题。如果编译器可以看到所有调用,则可以假设RAM没有被任何更改。因此,您必须在其周围放置例如互斥体,以确保编译器无法看到所有可能的访问,并且必须重新加载数据。

Placement new不会初始化POD。但是,您应该采取特殊措施来防止竞争条件,如互斥锁。这在很大程度上取决于你的设计,但是一个对象只有通过在堆栈上创建一个局部变量或者通过一个新的表达式才能存在。这就是为什么C++中只对某些内存进行了无效化,然后将其转换成任何想要的对象类型的原因。为什么这在mmap'd内存的情况下是合法的?@SumDood您不应该在堆栈上创建对象,而应该使用指针。因此,除了一个进程外,您使用的所有进程都是:myType*var=static\u cast(shared\u mem+offset);在一个过程中:myType*var=new(shared_mem+offset)(myType);