在开始之前,我想澄清两件事:
我不能在这个项目中使用Boost IPC,除了原始的C / C ++库,我不能使用任何东西。
我正在尝试将vector
存储在共享内存位置。我已经映射了一个共享内存页面并得到了它的指针。我还使用vector
在共享内存上创建了placement new
本身,并为其提供了地图视图的LPVOID
:
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
std::vector<int, shared_allocator<int>>* vec = new(pBuf) std::vector<int, shared_allocator<int>>;
现在,当我尝试从第二个进程访问内存时,我能够抓住vector
本身甚至打印其size()
。显然,我无法访问任何数据,因为它全部存储在第一个进程的堆中。
从代码中可以清楚地看到我正在使用我的自定义分配器,如下所示:
template <class T>
struct shared_allocator
{
typedef T value_type;
shared_allocator() noexcept {} //default ctor not required by C++ Standard Library
// A converting copy constructor:
template<class U> shared_allocator(const shared_allocator<U>&) noexcept {}
template<class U> bool operator==(const shared_allocator<U>&) const noexcept
{
return true;
}
template<class U> bool operator!=(const shared_allocator<U>&) const noexcept
{
return false;
}
T* allocate(const size_t n) const;
void deallocate(T* const p, size_t) const noexcept;
};
template <class T>
T* shared_allocator<T>::allocate(const size_t n) const
{
if (n == 0)
{
return nullptr;
}
if (n > static_cast<size_t>(-1) / sizeof(T))
{
throw std::bad_array_new_length();
}
//void* const pv = malloc(n * sizeof(T));
//if (!pv) { throw std::bad_alloc(); }
//return static_cast<T*>(pv);
return (T*) ::operator new(n*sizeof(T));
}
template<class T>
void shared_allocator<T>::deallocate(T * const p, size_t) const noexcept
{
// free(p);
delete(p);
}
此代码是在Microsoft's documentation之后完成的。
我将malloc
和free
替换为C ++ new
和delete
。上面的代码运行良好,第一个进程可以访问所有内容。
现在我试图修改分配器,以便在共享内存上分配新创建的对象。所以我将allocate
函数更改为:
template <class T>
T* shared_allocator<T>::allocate(const size_t n) const
{
if (n == 0)
{
return nullptr;
}
if (n > static_cast<size_t>(-1) / sizeof(T))
{
throw std::bad_array_new_length();
}
//void* const pv = malloc(n * sizeof(T));
//if (!pv) { throw std::bad_alloc(); }
//return static_cast<T*>(pv);
cnt += n*sizeof(T);
void* p = (void*) (static_cast<char*>(pBuf) + cnt);
return (T*) ::operator new(n*sizeof(T), p);
}
cnt
是一个以0开头的全局变量。
这显然不起作用。它崩溃了一些内存违规异常和所有。我尝试跟踪cnt
的更改,第一次增加16,然后增加4。
每次vector
内的_MyFirst()
被替换为共享内存中的地址时,vector
没有填充正确的数据。
我知道我做错了,但我已经看过很多地方,似乎无法弄清楚如何做对。如何修改allocator
以正确分配共享内存?如果它不能,那么我是否需要重新创建自己的vector
?
我一直在关注此article,它表明我只需要编写一个allocator
来完成这项工作。