Прежде чем я начну, я хотел бы прояснить две вещи:
Я не могу использовать 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. документация.
Я заменил 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
?
Я следил за этой статьей, и она показывает, что Мне нужно только написать allocator
, чтобы это заработало.
(char*)pBuf + sizeof(vector<int, shared_allocator<int> >) + cnt
? Поскольку вы построили вектор на месте в начале pBuf? - person PeterT   schedule 27.10.2017push_back(0)
и получал случайное значение какvec[0]
). . В любом случае,vec[0]
по-прежнему хранится в куче процесса, а не в разделяемой памяти. Мой второй процесс все еще не может видетьvec[0]
. - person Everyone   schedule 27.10.2017MapViewOfFileEx
с одним и тем же базовым адресом в обоих процессах. Не уверен, что это возможно в Windows, никогда не пробовал. Но теоретически использование одного и того же виртуального адреса в двух разных процессах должно быть в порядке. - person PeterT   schedule 27.10.2017MapViewOfFile2
, это позволит вам выбрать базовый адрес (хотя как вы выбираете действительный базовый адрес, я понятия не имею). - person Richard Critten   schedule 27.10.2017