3

我使用函数CreateFileMapping MapViewOfFile UnmapViewOfFile在磁盘上创建一个共享块。我可以在这个块上放置新的类对象吗?


我使用 VS2003 IDE。

try
{
    Sphere *pData = m_pBVH->GetFirstHalfData();
    Sphere *p = new(pData)Sphere(center, radius, index);
}
catch (std::exception& e)
{
    // Can't catch
}

放置新错误:

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

DebugMode 下,placement new运算符可能会导致语法错误。可能是因为上面的代码,注释掉再试试!

Release模式下,没关系,但抛出不是 std::bad_alloc 的异常,无法弄清楚它是哪个。也许共享内存的构建方式有些问题。我的共享内存创建代码如下:

CBVHVertexBuffer::CBVHVertexBuffer(const CString &file, unsigned int size)
{
    this->file = file;
    this->size = size;

    fileHandle = INVALID_HANDLE_VALUE;
    mapHandle = INVALID_HANDLE_VALUE;
    mapLength = 0;

    start = NULL;
    end = NULL;
    head = NULL;
    tail = NULL;

    fileHandle = ::CreateFile(
        file,
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_DELETE_ON_CLOSE,
        NULL);
    if (fileHandle != INVALID_HANDLE_VALUE) 
    {
        //::SetFilePointer(fileHandle, size * pickingVertexSize, NULL, FILE_BEGIN);
        //::SetEndOfFile(fileHandle);
        //mapLength = ::GetFileSize(fileHandle, NULL);
        //mapLength = size * pickingVertexSize;
        mapHandle = ::CreateFileMapping(fileHandle, NULL, PAGE_READWRITE, 0, size * pickingVertexSize, NULL);
        mapLength = ::GetFileSize(fileHandle, NULL);
        start = (Sphere*)::MapViewOfFile(mapHandle, FILE_MAP_WRITE, 0, 0, 0);
    }

    end = start + size;

    Clear();
}
4

2 回答 2

3

我建议只在映射文件中使用普通旧数据 (POD),因为在映射和取消映射文件时指针可能会变得无效

于 2013-06-13T08:31:27.210 回答
2

原则上,您可以使用placement new 运算符(void* operator new (std::size_t size, void* ptr) throw();)在已分配的内存缓冲区中创建对象。

但是,在文件映射区域中创建对象应该适用于 POD 对象。不建议将任何原始指针成员(和虚拟内存表,如果有)存储在映射文件中,因为一旦在不同的地址空间中完成映射,它们就会失效。在这种情况下,您还应该注意管理内存分配。

我建议看一下 boost 进程间库(它们对内存映射文件有很好的支持,包括内存缓冲区的管理 - 分配算法、对象跟踪和用于链接对象地址空间独立的类指针类(offset_ptr)) .

于 2013-06-13T08:36:19.853 回答