C++类构造中的指针
我这几天一直在努力解决这个问题。
在这个程序中,有一个从字符串键到结构体值的unordered_map
。这个想法是可行的,但是当我将 unordered_map
放入一个类中,然后更轻松地访问它时,我收到一个错误:
Eliminare.exe!std::_Hash<std::_Umap_traits<std::string,Data,std::_Uhash_compare<std::string,std::hash<std::string>,std::equal_to<std::string>>,boost::interprocess::allocator<std::pair<std::string,Data>,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,__int64,unsigned __int64,0>,0>,boost::interprocess::iset_index>>,0>>::_Find_last<std::string>(const std::string & _Keyval, const unsigned __int64 _Hashval) Row 1510 C++
Eliminare.exe!std::unordered_map<std::string,Data,std::hash<std::string>,std::equal_to<std::string>,boost::interprocess::allocator<std::pair<std::string,Data>,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,__int64,unsigned __int64,0>,0>,boost::interprocess::iset_index>>>::at(const std::string & _Keyval) Riga 387 C++
Eliminare.exe!MapCreator::getValue(std::string Key) Row 37 C++
Eliminare.exe!main() Row 7 C++
这是主要内容:
#include "MapCreator.h"
int main() {
MapCreator mappaClass;
auto values = mappaClass.getValue("value");
}
虽然这是在 MapCreator.h 中:
#pragma once
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <unordered_map>
#include<iostream>
typedef struct Data
{
int a;
int b;
}dataClass;
namespace bost = boost::interprocess;
typedef std::string KeyType;
typedef dataClass MappedType;
typedef std::pair<std::string, dataClass> ValueType;
typedef bost::allocator<ValueType, bost::managed_shared_memory::segment_manager> ShmemAllocator;
typedef std::unordered_map<KeyType, MappedType, std::hash<KeyType>, std::equal_to<KeyType>, ShmemAllocator> MySHMMap;
class MapCreator
{
public:
MySHMMap* mappa = nullptr;
MapCreator() {
bost::shared_memory_object::remove(nameMemory);
bost::managed_shared_memory segment(bost::create_only, nameMemory, sizeDeclared);
ShmemAllocator alloc_inst(segment.get_segment_manager());
mappa = segment.construct<MySHMMap>("MySHMMapName")(alloc_inst);
dataClass value;
value.a = 12;
value.b = 1111;
mappa->insert(std::pair<std::string, dataClass>("value", value));
std::cout << mappa->at("value").a;
}
dataClass getValue(std::string Key) {
return mappa->at(Key);
}
private:
const int sizeDeclared = 65536;
const char nameMemory[20] = "SharedMemoryName";
};
“cout
”在MapCreator
构造函数中正确打印“12”,但是使用getValue
函数,它打印上面提到的错误。
感谢您的帮助,如果您对代码有任何疑问,请提问。
信息:
- 编译器:Visual C++ 和 Visual Studio 2022
- 没有该类的代码运行良好,
- boost 类的版本是:1.78.0
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
有多个问题。
第一个是
segment
是构造函数中的局部变量,这意味着mappa
在构造函数返回后是一个悬空指针。其次,更大的问题是您的映射正确使用共享内存分配器,但字符串却没有。字符串也是动态分配的,因此除非您使字符串也使用共享内存,否则您的解决方案将无法工作。
开始修复:
在执行中存在额外的复杂性:
segment
code> 必须是一个字段,但它只能从初始化列表构造(或使用 NSMI)。这意味着我们必须让remove
也出现在初始化列表中(在此之前)。这是我的初步尝试:我发现
std::hash
实际上并不是专门用于MyString
实例,因为我知道我想改变这一点,无论如何我不会浪费时间来创建哈希函数对象。相反,我切换到boost::unordered_map
以便使用boost::hash<>
这已经可以工作Live On Coliru
打印:
改进
作用域分配器
allocator/get_segment_manager() 周围的事情非常笨拙。使用作用域分配器可以缓解这种情况:
现在你可以“简单地”写:
而不是之前的复杂版本。 在 Coliru 上直播
异构键查找
在我们构造
MyString
的另一个地方(只是为了在at()
调用之后将其丢弃...),我们可以使用boost: :unordered_map
的兼容键查找:这需要哈希和相等性兼容:
查看在 Coliru 上直播
使用 C++20 标准 unordered_map 代替(请参阅https://en.cppreference.com/w/cpp/container/unordered_map/find):
然后:
也可以查看在 Coliru 上直播< /p>
There are multiple issues.
The first one is that
segment
is a local variable in your constructor, meaning thatmappa
is a dangling pointer after the constructor returns.Second, bigger, problem is that your map uses a shared memory allocator correctly, but the strings do NOT. String are also dynamically allocating, so your solution cannot work unless you make the string also use shared memory.
Starting the fix:
In the execution there's additional complexity:
segment
must be a field, but it can only be constructed from the initializer list (or using NSMI). That means that we have to make theremove
also occur (before that) in the initializer list. Here's my initial attempt:I found out that
std::hash
isn't actually specialized for theMyString
instance, and because I know down the line I'd want to change that anyways I'm not wasting time to create a Hash function object. Instead, I'm switching toboost::unordered_map
just soboost::hash<>
is usedThis is already working Live On Coliru
Prints:
Improvements
Scoped Allocators
Things are pretty clunky around the allocator/get_segment_manager(). Using scoped-allocators you can alleviate that:
Now you can "simply" write:
Instead of the complicated version before. Live On Coliru
Heterogenous Key Lookup
The other place where we are constructing
MyString
(just to throw it away after theat()
call...), we can useboost::unordered_map
's compatible-key lookup:This requires the hash and equality to be compatible:
See it Live On Coliru
Using C++20 standard unordered_map instead (see https://en.cppreference.com/w/cpp/container/unordered_map/find):
And then:
See it Live On Coliru as well