我使用 boost :: iterator_range 获得无效的读取/分段错误错误。 我的数据在哪里超出范围,我该如何防止这种情况发生?
以下是一些重现问题的代码:
#include <iostream>
#include <vector>
#include <map>
#include <boost/shared_ptr.hpp>
#include <boost/range.hpp>
#include <boost/range/iterator_range.hpp>
这些是我的类型:
typedef double Value;
typedef std::vector<Value> vValue;
typedef boost::iterator_range<std::vector<Value>::iterator> rValue;
效用函数:
void print_range(const rValue &r) {
for(rValue::difference_type i = 0; i < r.size(); ++i) std::cout << r[i] << " ";
std::cout << std::endl;
}
这是一个存储所有数据缓存的对象。
class MyDataObject { // This object stores ALL DATA.
private:
vValue data;
public:
void setData(vValue data) {
this->data = data;
}
vValue &getData() {
return data;
}
};
然后使用boost :: iterator_range将数据段创建为所有数据的子集。
class DataSegment { // This object points to a subset of all data using boost::iterator_range
private:
rValue data;
public:
void setData(rValue data) {
this->data = data;
}
rValue& getData() {
return data;
}
};
实际数据库实施:
class DB { // The database caches ALL DATA and then returns a subset using boost::iterator_range when asked for.
private:
std::map<std::string, MyDataObject> cache;
public:
DB() {
//
}
MyDataObject loadIntoCache(std::string key) {
vValue data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
MyDataObject obj;
obj.setData(data);
cache[key] = obj;
return obj;
}
boost::shared_ptr<DataSegment> getMemoryEfficientSubset() {
MyDataObject obj = loadIntoCache("bar"); // If bar is not in cache, load it.
rValue data = obj.getData();
boost::shared_ptr<DataSegment> segment(new DataSegment());
rValue out = boost::make_iterator_range(data.begin() + 2, data.begin() + 7);
segment->setData(out);
return segment;
}
};
测试代码:
int main() {
DB *db = new DB();
boost::shared_ptr<DataSegment> segment = db->getMemoryEfficientSubset();
print_range(segment->getData()); // ERROR: segfault within print_range. Valgrind says "Invalid read of size 8"
delete db;
return 0;
}
答案 0 :(得分:1)
最终存储在*segment
中的迭代器范围与data
相关联,loadIntoCache
是调用的本地范围。据推测,您的意思是MyDataObject&
返回cache[key] = obj
(例如obj
初始化),只要缓存为空,它就会保持有效。还要确保loadIntoCache
是对data
的调用结果的引用,而不是副本,同样适用于obj.getData()
和调用{{1}}的结果。< / p>
答案 1 :(得分:0)
我通过使用指针解决了我的问题。
#include <iostream>
#include <vector>
#include <map>
#include <boost/shared_ptr.hpp>
#include <boost/range.hpp>
#include <boost/range/iterator_range.hpp>
typedef double Value;
typedef std::vector<Value> vValue;
typedef boost::iterator_range<std::vector<Value>::iterator> rValue;
void print_range(const rValue &r) {
for(rValue::difference_type i = 0; i < r.size(); ++i) std::cout << r[i] << " ";
std::cout << std::endl;
}
class MyDataObject { // This object stores ALL DATA.
private:
vValue data;
public:
void setData(vValue data) {
this->data = data;
}
vValue& getData() {
return data;
}
};
class DataSegment { // This object points to a subset of all data using boost::iterator_range
private:
rValue data;
public:
void setData(rValue data) {
this->data = data;
}
rValue& getData() {
return data;
}
};
class DB { // The database caches ALL DATA and then returns a subset using boost::iterator_range when asked for.
private:
std::map<std::string, MyDataObject*> cache;
public:
DB() {
//
}
MyDataObject *loadIntoCache(std::string key) {
vValue data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
MyDataObject *obj = new MyDataObject();
obj->setData(data);
cache[key] = obj;
return obj;
}
boost::shared_ptr<DataSegment> getMemoryEfficientSubset() {
MyDataObject *obj = loadIntoCache("bar"); // If bar is not in cache, load it.
rValue data = obj->getData();
boost::shared_ptr<DataSegment> segment(new DataSegment());
rValue out = boost::make_iterator_range(data.begin() + 2, data.begin() + 7);
segment->setData(out);
return segment;
}
~DB() {
for(std::map<std::string, MyDataObject*>::iterator i = cache.begin(); i != cache.end(); ++i) delete i->second;
}
};
int main() {
DB *db = new DB();
boost::shared_ptr<DataSegment> segment = db->getMemoryEfficientSubset();
print_range(segment->getData()); // ERROR: segfault within print_range. Valgrind says "Invalid read of size 8"
delete db;
return 0;
}