我使用Rocksdb作为程序(C++(的数据库。对于其中一个用例,我正在制作以下格式的密钥来存储:key=<修复前缀>lt;字符串类型元素>lt;foo类型>
我在访问";字符串类型元素";来自密钥的数据:
Received signal: Segmentation fault (11)
迭代存储数据的代码类似于:
auto prefix = // defined here
auto from = // defined here
auto to = // defined here
std::unique_ptr<rocksdb::Transaction> trans(db_.BeginTransaction(rocksdb::WriteOptions()));
rocksdb::ReadOptions opts;
opts.snapshot = trans->GetSnapshot();
std::unique_ptr<rocksdb::Iterator> iter(trans->GetIterator(opts));
iter->Seek(from);
for (; iter->Valid() && iter->key().compare(to) < 0; iter->Next())
{
if (iter->key().starts_with(prefix))
{
// This line of code is producing the error
const auto string-type-element = *reinterpret_cast<const string-type*>(iter->key().data() + prefix.size());
// some stuffs here
}
}
我的尝试:
正如你在上面的代码中看到的,我指出了错误的一行。由于错误是Segmentation fault(11(,这通常意味着尝试未定义/在内存位置之外,所以我的猜测是reinterpret_cast无法推导出"0"的大小;字符串类型元素";元素std::string不是固定大小,不像";int";等等,并且它最终访问它不应该访问的存储器部分。。。
我想问:
- 如果由于大小未知,无法从键之间提取std::string,我们该怎么办
- 我提到的这个问题还有其他原因吗?如何处理
reinterpret_cast
是一个非常危险的工具,只能在特殊情况下使用,而这里没有。查看std::string构造函数,您会发现其中一个构造函数接受指向以null结尾的字符数组的指针。目前还不清楚iter->key().data()
的类型是什么,但如果它是一个以null结尾的字符串,您可以将行更改为:
const auto string-type {iter->key().data() + prefix.size()};
从前缀后的数据部分初始化字符串类型。
在您的案例中,reinterpret_cast
试图假装所指向的数据是一个字符串对象,它不仅仅是字符类型的原始字节,而且还有其他元素。