2012-10-17 76 views
0

我得到無效讀取/分段錯誤錯誤使用boost :: iterator_range。 我的數據在哪裏超出範圍,我如何防止發生這種情況?使用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; 
} 

回答

1

最終存儲在*segment該迭代範圍與data,其是本地的呼叫相關聯。假定你的意思是loadIntoCache返回一個MyDataObject&(從例如cache[key] = obj初始化),只要高速緩存存在,它將保持有效。請確保obj是對loadIntoCache的調用結果的參考,而不是副本,並且類似地對於data和調用obj.getData()的結果也是如此。

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; 
}