【问题标题】:reducing size of a stringstream减小字符串流的大小
【发布时间】:2013-09-11 23:37:29
【问题描述】:

作为一种存储多个状态日志等的简单方法。我选择了std::stringstream。如果出现错误,我可以简单地将.rdbuf() 转储到一个文件中,以便能够重现我的程序在崩溃之前所做的事情。

我现在的问题是,这个字符串流的大小会无限增长。我已经尝试了几件事来确保我只保留流的最后 1MiB 左右,但没有成功。

  1. .rdbuf()->pubseekoff(...)
  2. .ignore(...)
  3. getline(...)
  4. ss.str() = ss.str().substr(...)

显然,底层缓冲区对象总是只会增加大小 - 无论是否已读取某些数据。

有什么方法可以减小大小/将其保持在某个常数(最好没有常规的深拷贝)? 作为底层缓冲区对象的循环缓冲区将是完美的 - 这可能吗?特别是。已经存在了吗?


编辑: 解决方案基本上必须表现得像一个流。它由 procompiler 放置,而不是 std::err 或直接文件流(类似于 boost::log)。因此,使用字符串流不是绝对必要的,但非常有用。 (否则我必须实现所有 ostream 的东西才能流式传输 std::endl...)

【问题讨论】:

  • 您是否考虑过只使用std::ofstream 并直接刷新到日志文件?
  • @AJG85 它变得太大了。该程序必须 24/7 全天候运行,并且每天会创建数 GiB 的数据。无论如何,我真的不需要所有这些日志 - 我只对崩溃前的最后几分钟(或几秒钟)感兴趣。
  • 有一个叫做“日志轮换”的原则听起来很适用。您保留一两个“旧”和一个“当前”日志文件。每 X 个单位时间,您将“当前”更改为较旧的一个,并删除最旧的。在 linux 中,甚至有工具可以为您执行此操作,只要日志打印足够频繁地打开和关闭文件(如果文件一直保持打开状态,您只需继续写入已删除的旧文件,因为 Unix 风格的文件系统就是这样工作的)。
  • 磁盘便宜,内存不便宜。记录器的常见设计是使用滚动文件。当您超过某个大小时,您关闭并重命名文件索引,删除或归档最旧的文件,然后打开一个新文件。理想情况下,这将是可配置的。对于我实现的电信服务器,它也运行 24/7,我几乎打印了每个线程的每个方法的每个入口和出口,并发现 20 个文件,每个 25MB 足以跟踪大多数站点的任何问题。
  • @MatsPetersson 我看你打字速度更快 ;-)

标签: c++ c++11 std stringstream


【解决方案1】:

在我当前的 STL 实现(VS2010 SP1)中,str("") 释放所有内存

std::stringstream ss;
for(unsigned int i = 0; i<10000000; ++i)
{
    ss << "QWERTYUIOPASDFGHJKLXCVBNM";
}

ss.str(""); // memory released here

Reference: "在内部,函数调用其内部字符串缓冲区对象的 str 成员。"

我将这句话解释为如果我分配一个空字符串,它将复制构造底层缓冲区。

【讨论】:

  • 我错误地调用了ss.str() = 假设.str() 来返回一个引用......我仍然认为即使.str("") 也不会释放我的实现(gcc 4.8)的内存,但是标准可能打算释放内存(某些实现这样做)。所以你的答案在技术上是正确的(我会接受),即使我最终不得不实现几个字符串流的轮换......
  • 奇怪的是,内存不应该在 gcc 上被释放。重置对象也会重置读取和写入偏移量。唯一的可能性是底层流缓冲区是否以某种方式保留了内存,因为外部抽象确实在重置后报告了 0;见这里:coliru.stacked-crooked.com/a/d66fbc86e6c1c220 当然调用 pbase() 会更有意义。不过,我很高兴你的问题得到了解决!
  • @Nikos 是的,但是 OP 的意图是在回收字符串流对象时释放未使用的内存。
猜你喜欢
  • 2022-01-21
  • 2013-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-17
  • 1970-01-01
  • 1970-01-01
  • 2010-10-03
相关资源
最近更新 更多