0

我使用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;
}
4

2 回答 2

1

最终存储在其中的迭代器范围与调用本地*segment相关联。data大概您打算loadIntoCache返回一个MyDataObject&(从 eg 初始化cache[key] = obj),只要缓存存在,它就会保持有效。还要确保它obj是对调用结果的引用,而loadIntoCache不是副本,并且同样是对data调用结果的引用obj.getData()

于 2012-10-17T16:14:44.743 回答
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;
}
于 2012-10-17T16:20:58.763 回答