将 New 放置在 SharedMemory 中已有的对象上

Placement New on already existing object in SharedMemory

我有两个程序。第一个分配一个共享内存文件,第二个从中读取。我正在使用 placement-new 将对象放入此内存 gua运行teeing 对象不使用 new 或分配任何内存在共享内存文件之外。

我的数组结构:

template<typename T, size_t Size>
struct SHMArray {
    SHMArray() : ptr(elements) {}
    SHMArray(const SHMArray& other) { std::copy(other.begin(), other.end(), begin()); }

    SHMArray(SHMArray&& other)
    {
        std::swap(other.ptr, ptr);
        std::fill_n(ptr.get(), Size, T());
    }

    ~SHMArray()
    {
        std::fill_n(ptr.get(), Size, T());
    }

    constexpr bool empty() const noexcept
    {
        return Size == 0;
    }

    constexpr size_type size() const noexcept
    {
        return Size;
    }

    T& operator[](std::size_t pos)
    {
        return *(ptr.get() + pos);
    }

    constexpr const T& operator[](std::size_t pos) const
    {
        return *(ptr.get() + pos);
    }

    T* data() noexcept
    {
        return ptr.get();
    }

    constexpr const T* data() const noexcept
    {
        return ptr.get();
    }

private:
    offset_ptr<T> ptr;
    T elements[];
};

计划 1:

int main()
{
    //Allocate a shared memory file of 1mb..
    auto memory_map = SharedMemoryFile("./memory.map", 1024 * 1024, std::ios::in | std::ios::out);

   memory_map.lock();

   //Pointer to the shared memory.
   void* data = memory_map.data();

   //Place the object in the memory..
   SHMArray<int, 3>* array = ::new(data) SHMArray<int, 3>();
   (*array)[0] = 500;
   (*array)[1] = 300;
   (*array)[2] = 200;

   memory_map.unlock(); //signals other program it's okay to read..
}

计划 2:

int main()
{
    //Open the file..
    auto memory_map = SharedMemoryFile("./memory.map", 1024 * 1024, std::ios::in | std::ios::out);

   memory_map.lock();

   //Pointer to the shared memory.
   void* data = memory_map.data();

   //Place the object in the memory..
   //I already understand that I could just cast the `data` to an SHMArray..
   SHMArray<int, 3>* array = ::new(data) SHMArray<int, 3>();
   for (int i = 0; i < array.size(); ++i)
   {
       std::cout<<(*array)[i]<<"\n";
   }

   memory_map.unlock(); //signals other program it's okay to read..
}
  1. 程序一将 SHMArray 放入内存中并放置新的。程序二在程序一个已经放置的对象之上做同样的事情(覆盖它)。这是未定义的行为吗?我不认为是,但我想确认一下。

  2. 两个程序都没有调用析构函数array->~SHMVEC();我也不认为这会泄漏,只要我关闭 MemoryMapped 文件就应该没问题..但我想确保这可以。如果我 运行 在同一个文件上再次运行这些程序,应该没有问题。

我基本上是在假设 placement new 的工作方式就像我在这个特定场景中通过以下方式在内存中放置了一个 C 结构:struct SHMArray* array = (struct SHMArray*)data;..这是正确的吗?

I am essentially making the assumption that placement new is working as if I placed a C struct in memory in this particular scenario via: struct SHMArray* array = (struct SHMArray*)data;.. Is this correct?

不,这是不正确的。 Placement new 还会调用对象的适当构造函数。 “struct SHMArray* array = (struct SHMArray*)data;”不调用任何对象的构造函数。这只是一个指针转换转换。这不会调用任何人的构造函数。关键区别。

在您的示例代码中,您确实想要调用模板化对象的构造函数。尽管显示的示例还有其他问题,正如评论中已经提到的那样,但这似乎是在这种特定情况下需要做的事情。

但就新放置与指针转换的等效而言,不,它们并不相同。一个调用构造函数,一个不调用。 new 总是调用构造函数,无论是否放置 new。这是一个非常重要的细节,不容忽视。