我试图使用的std :: string作为一个关键的stxxl ::地图插入是罚款少数串约10-100的。 但是,当试图插入大量关于这10万串,我得到段错误。
代码如下:
struct CompareGreaterString {
bool operator () (const std::string& a, const std::string& b) const {
return a > b;
}
static std::string max_value() {
return "";
}
};
// template parameter <KeyType, DataType, CompareType, RawNodeSize, RawLeafSize, PDAllocStrategy (optional)>
typedef stxxl::map<std::string, unsigned int, CompareGreaterString, DATA_NODE_BLOCK_SIZE, DATA_LEAF_BLOCK_SIZE> name_map;
name_map strMap((name_map::node_block_type::raw_size)*3, (name_map::leaf_block_type::raw_size)*3);
for (unsigned int i = 0; i < 1000000; i++) { /// Inserting 1 million strings
std::stringstream strStream;
strStream << (i);
Console::println("Inserting: " + strStream.str());
strMap[strStream.str()]=i;
}
在这里,我无法确定为什么我无法插入多个字符串的数量。 我正好收到分段错误而将“1377”。 加上我能够作为键添加任何整数数量。 我觉得字符串变量大小可能会导致这样的麻烦。
另外,我无法理解什么返回max_value
的字符串。 我简单地返回一个空字符串。
根据文档 :
CompareType还必须提供一个静态MAX_VALUE方法,它返回类型关键字类型的值,该值是比存储在地图任意键较大
因为空字符串恰好比较比其他任何字符串作为小,它打破了这个先决条件,因此可能会导致不确定的行为。
这里有一个max_value
应该工作。 MAX_KEY_LEN
仅仅是一个整数,其是大于或等于最长可能字串密钥的长度,该地图可以有。
struct CompareGreaterString {
// ...
static std::string max_value() {
return std::string(MAX_KEY_LEN, std::numeric_limits<unsigned char>::max());
}
};
我终于找到了解决我的问题与蒂莫bingmann,user2079303和马丁·巴很大的帮助。 谢谢。
我愿与你分享。
首先stxxl只支持POD。 这意味着它只能存储固定大小的结构。 因此的std :: string不能是一个关键。 stxxl ::因为它们包含在物理内存本身的地图工作约100-1000字符串。 当更多的字符串插入它到磁盘上在内部引发了一些问题写。
因此,我们需要利用炭[]如下使用固定的字符串:
static const int MAX_KEY_LEN = 16;
class FixedString {
public:
char charStr[MAX_KEY_LEN];
bool operator< (const FixedString& fixedString) const {
return std::lexicographical_compare(charStr, charStr+MAX_KEY_LEN,
fixedString.charStr, fixedString.charStr+MAX_KEY_LEN);
}
bool operator==(const FixedString& fixedString) const {
return std::equal(charStr, charStr+MAX_KEY_LEN, fixedString.charStr);
}
bool operator!=(const FixedString& fixedString) const {
return !std::equal(charStr, charStr+MAX_KEY_LEN, fixedString.charStr);
}
};
struct comp_type : public std::less<FixedString> {
static FixedString max_value()
{
FixedString s;
std::fill(s.charStr, s.charStr+MAX_KEY_LEN, 0x7f);
return s;
}
};
请注意,所有的主要运营商(()==,=!)需要被重写所有stxxl ::地图功能,现在的工作,我们可以定义fixed_name_map在地图如下:
typedef stxxl::map<FixedString, unsigned int, comp_type, DATA_NODE_BLOCK_SIZE, DATA_LEAF_BLOCK_SIZE> fixed_name_map;
fixed_name_map myFixedMap((fixed_name_map::node_block_type::raw_size)*5, (fixed_name_map::leaf_block_type::raw_size)*5);
现在该程序编译细且正在接受大约10 ^ 8个串没有任何问题。 我们也可以用myFixedMap比如std ::地图本身。 {用于离:myFixedMap [fixedString] = 10}
如果使用的是C ++ 11,然后作为替代可以使用的FixedString类std::array<char, MAX_KEY_LEN>
这是一个普通的固定大小的数组c的顶部,因为你是从的std :: string用于实施比较和迭代器的STL层,但它是一个POD类型 ,所以STXXL应该支持。
或者,也可以在使用serialization_sort TPIE 。 它可以排序类型的元素std::pair<std::string, unsigned int>
就好了,所以如果你需要的是插入散装一切,然后访问它散装,这将是足以让你的情况(也可能快视具体情况)。