【发布时间】:2015-06-02 19:39:18
【问题描述】:
我创建了以下代码来测试共享内存分配器和容器..
分配器(只保留指向内存块的指针+大小的基本分配器:
template<typename T>
struct SharedMemoryAllocator
{
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
void* memory;
std::size_t size;
SharedMemoryAllocator(void* memory, std::size_t size) noexcept : memory(memory), size(size) {};
SharedMemoryAllocator(const SharedMemoryAllocator& other) noexcept : memory(other.memory), size(other.size) {};
template<typename U>
SharedMemoryAllocator(const SharedMemoryAllocator<U>& other) noexcept : memory(other.memory), size(other.size) {};
template<typename U>
SharedMemoryAllocator& operator = (const SharedMemoryAllocator<U>& other) { return *this; }
SharedMemoryAllocator<T>& operator = (const SharedMemoryAllocator& other) { return *this; }
~SharedMemoryAllocator() {}
pointer address(reference value) const {return &value;}
const_pointer address(const_reference value) const {return &value;}
pointer allocate(size_type n, const void* hint = 0) {return static_cast<T*>(memory);}
void deallocate(T* ptr, size_type n) {}
template<typename U, typename... Args>
void construct(U* ptr, Args&&... args) {::new(static_cast<void*>(ptr)) U(std::forward<Args>(args)...);}
void construct(pointer ptr, const T& val) {new(static_cast<T*>(ptr)) T(val);}
template<typename U>
void destroy(U* ptr) {ptr->~U();}
void destroy(pointer ptr) {ptr->~T();}
size_type max_size() const {return size / sizeof(T);}
template<typename U>
struct rebind {typedef SharedMemoryAllocator<U> other;};
};
template <typename T, typename U>
inline bool operator == (const SharedMemoryAllocator<T>& a, const SharedMemoryAllocator<U>& b)
{
return (a == b);
}
template <typename T, typename U>
inline bool operator != (const SharedMemoryAllocator<T>& a, const SharedMemoryAllocator<U>& b)
{
return !(a == b);
}
容器(只是一个使用 SharedMemory 分配器分配内存的容器):
template<typename T, typename allocator = std::allocator<T>>
class CVector
{
private:
T* memory;
std::size_t size, capacity;
allocator alloc;
public:
CVector() : memory(nullptr), size(0), capacity(0), alloc(allocator()) {}
CVector(const allocator &alloc) : memory(nullptr), size(0), capacity(0), alloc(alloc) {}
~CVector()
{
if(memory)
{
for(std::size_t i = 0; i < this->size; ++i)
{
alloc.destroy(memory + i);
}
alloc.deallocate(memory, capacity);
memory = nullptr;
}
}
void reserve(std::size_t size)
{
if(capacity < size)
{
capacity = size;
void* mem = alloc.allocate(capacity);
if(memory && memory != mem)
{
memcpy(static_cast<char*>(mem), memory, size * sizeof(T));
for(std::size_t i = 0; i < this->size; ++i)
{
alloc.destroy(memory + i);
}
alloc.deallocate(memory, capacity);
memory = nullptr;
}
memory = static_cast<T*>(mem);
}
}
void push_back(T&& value)
{
if(capacity == 0)
{
reserve(1);
}
if(size >= capacity)
{
reserve(capacity * 2);
}
alloc.construct(memory + size++, value);
}
T& operator[](std::size_t size)
{
return *(memory + size);
}
const T& operator[](std::size_t size) const
{
return *(memory + size);
}
};
主要:
int main()
{
MemoryMap mem{"Local\\Test", 5000, std::ios::in | std::ios::out};
mem.open();
mem.map();
typedef CVector<int, SharedMemoryAllocator<int>> SHMVec;
SHMVec* vec = ::new(mem.data()) SHMVec(SharedMemoryAllocator<int>(static_cast<char*>(mem.data()) + sizeof(SHMVec), 1024 - sizeof(SHMVec)));
vec->reserve(100);
vec->push_back(100);
vec->push_back(200);
vec->push_back(300);
std::cout<<"Address: "<<mem.data()<<"\n";
std::cin.get();
SHMVec* ptrVec = reinterpret_cast<SHMVec*>(mem.data());
std::cout<<(*ptrVec)[0];
vec->~SHMVec();
}
我在某处读到 std::vector 不能放在 SharedMemory 中,因为它可能会在当前进程的地址空间中对其自身进行一些跟踪。所以我决定编写自己的“向量”,它只是一个便宜的类。
接下来,我分配一个共享内存块,并将容器构造到该块中,如上面“main”中所示。
在另一个程序中,我做(主):
int main()
{
MemoryMap mem{"Local\\Test", 5000, std::ios::in};
mem.open();
mem.map();
typedef CVector<int, SharedMemoryAllocator<int>> SHMVec;
std::cout<<"Address: "<<mem.data()<<"\n";
SHMVec* ptrVec = reinterpret_cast<SHMVec*>(mem.data());
std::cout<<(*ptrVec)[0];
}
当两个程序都在 0x370000 映射共享内存块时,它可以工作。但是,如果一个程序在 0x370000 分配 SharedMemoryBlock,第二个在 0x380000 分配,它就会崩溃(第二个程序在尝试访问第一个创建的容器时崩溃)。
任何想法为什么会发生这种情况?容器在共享内存块中。为什么块的地址必须完全相同?
【问题讨论】:
-
“严重崩溃”是您的问题描述吗?
-
好吧.. 如果有帮助,它会因“访问冲突”而崩溃。我只想知道为什么共享内存块必须在两个进程中分配到相同的地址。
-
不,它没有帮助。加载你的调试器。
-
是的,调试器会帮助您找出原因。将调试器附加到两个进程(或启动两个调试器)并从两侧对其进行攻击。它还将为您提供堆栈跟踪以及单步执行代码以确保您的变量包含预期值的能力。
-
“调试器将如何帮助我?” 让您更多地了解您的程序正在做什么,而不是“它严重崩溃”。这是基本软件开发。没有调试器你怎么工作???
标签: c++ containers shared-memory