我正在编写一个小程序来处理一个大的文本文件并做一些替换。问题是它从来没有停止分配新的内存,所以它最终耗尽内存。我已经将其简化为一个简单的程序,它只计算行数(请参阅下面的代码),同时仍然分配越来越多的内存。我必须承认,我对激励和振奋精神知之甚少。你能告诉我我做错了什么吗?多谢百万!
#include <string>
#include <iostream>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
// Token ids
enum token_ids {
ID_EOL= 100
};
// Token definition
template <typename Lexer>
struct var_replace_tokens : boost::spirit::lex::lexer<Lexer> {
var_replace_tokens() {
this->self.add ("\n", ID_EOL); // newline characters
}
};
// Functor
struct replacer {
typedef bool result_type;
template <typename Token>
bool operator()(Token const& t, std::size_t& lines) const {
switch (t.id()) {
case ID_EOL:
lines++;
break;
}
return true;
}
};
int main(int argc, char **argv) {
size_t lines=0;
var_replace_tokens< boost::spirit::lex::lexertl::lexer< boost::spirit::lex::lexertl::token< boost::spirit::istream_iterator> > > var_replace_functor;
cin.unsetf(std::ios::skipws);
boost::spirit::istream_iterator first(cin);
boost::spirit::istream_iterator last;
bool r = boost::spirit::lex::tokenize(first, last, var_replace_functor, boost::bind(replacer(), _1, boost::ref(lines)));
if (r) {
cerr<<"Lines processed: "<<lines<<endl;
} else {
string rest(first, last);
cerr << "Processing failed at: "<<rest<<" (line "<<lines<<")"<<endl;
}
}发布于 2016-11-09 20:51:34
这种行为是故意的。
multi_pass迭代器适配器。因为没有语法,圣灵不知道什么时候它可以被冲洗。..。istream_iterator负责读取输入流,而不必将整个流存储到内存中。是。但是你没有使用std::istream_iterator。你在使用助推器。是一个解析器生成器。解析器需要随机访问来进行回溯。
Spirit支持输入迭代器,方法是将输入序列调整为带有multi_pass适配器的随机访问序列。此迭代器适配器为回溯目的存储可变大小的缓冲区。某些操作(期望点,总是贪婪的操作符,如Kleene-*等)告诉解析器框架什么时候刷新缓冲区是安全的。
问题是:
你不是在解析,只是在标记。没有任何东西告诉迭代器要刷新它的缓冲区。
缓冲区是无限的,因此内存使用量增加。当然,这不是泄漏,因为一旦多通适应迭代器的最后一次副本超出范围,共享回溯缓冲区就会被释放。
解决办法:
最简单的解决方案是使用随机访问源。如果可以,请使用内存映射文件。
其他解决方案包括告诉多通道适配器冲洗。实现这一目标的最简单方法是使用tokenize_and_parse。即使有了像*(any_token)这样的伪语法,这也足以让解析器框架相信你不会要求它回溯。
灵感:
wc -l等工具进行比较默认情况下,pass.html存储共享deque。在使用dd if=/dev/zero bs=1M | valgrind --tool=massif ./sotest运行测试一段时间后查看它

清楚地显示所有的记忆
100.00% (805,385,576B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->99.99% (805,306,368B) 0x4187D5: void boost::spirit::iterator_policies::split_std_deque::unique<char>::increment<boost::spirit::multi_pass<std::istream, boost::spirit::iterator_policies::default_policy<boost::spirit::iterator_policies::ref_counted, boost::spirit::iterator_policies::no_check, boost::spirit::iterator_policies::istream, boost::spirit::iterator_policies::split_std_deque> > >(boost::spirit::multi_pass<std::istream, boost::spirit::iterator_policies::default_policy<boost::spirit::iterator_policies::ref_counted, boost::spirit::iterator_policies::no_check, boost::spirit::iterator_policies::istream, boost::spirit::iterator_policies::split_std_deque> >&) (in /home/sehe/Projects/stackoverflow/sotest)
| ->99.99% (805,306,368B) 0x404BC3: main (in /home/sehe/Projects/stackoverflow/sotest)https://stackoverflow.com/questions/40504267
复制相似问题