【问题标题】:C++: std::istream read and its calls to std::streambuf underflowC++:std::istream 读取及其对 std::streambuf 的调用下溢
【发布时间】:2012-06-17 18:21:20
【问题描述】:

以下代码仅测试在 std::stringbuf 上使用 std::istream read 时调用 underflow 的频率。

#include <iostream>
#include <vector>
#include <sstream>

class TestStringBuf : 
public std::stringbuf
{
public:

    int_type underflow()
    {
        std::cout<<"TestStringBuf underflow"<<std::endl;
        return std::stringbuf::underflow();
    }
};

int main(int argc, const char * argv[])
{
    TestStringBuf buf;
    std::iostream stream(&buf);

    stream << "tesr";

    std::vector<char> data(4);
    stream.read(&data[0], 4);

    for(int i=0; i<data.size(); ++i)
        std::cout<<data[i];
    std::cout<<std::endl;

    return 0;
}

输出是:

TestStringBuf underflow
TestStringBuf underflow
test

我希望只调用一次下溢,因为我准确地读取了 get 区域中存在的字节数,那么为什么要再次下溢呢?这是预期的行为吗? 我问是因为我的自定义 underflow 方法可能会长时间阻塞以读取新数据,因此在这种情况下,第二次调用 underflow 并不是很理想。

我在 Osx 上使用 clang 3.1libc++

谢谢!

更新:

我刚刚做了一个完全独立的测试,在我看来这是 libc++ 实现中的一个奇怪之处,因为 libstd++ 不会发生这种情况。有人可以用其他实现来测试吗?这是一个错误还是只是一个实现差异(对我来说感觉很糟糕)。我更新了上面的代码,因此您可以将其复制并粘贴到任何 main.cpp 中。

更新2:

毕竟这是 libc++ 中的一个错误,请参阅:http://llvm.org/bugs/show_bug.cgi?id=13113。如果你自己编译 libc++,这个 bug 应该会消失,我会尽快尝试。

【问题讨论】:

  • 当它越过位置 3 到流的末尾时可能会调用下溢?
  • 但为什么要超过位置 3?我希望它在随后调用 get() 或 read() 及其兄弟姐妹时超过位置 3。

标签: c++ istream streambuf


【解决方案1】:

C++ 标准明确允许 std::basic_stringbuf 的实现将字符序列存储在 std::basic_string 中,而不是使用 std::basic_streambuf 的内部缓冲区。

【讨论】:

  • 我不确定这与问题有何关系。为了示例的简单性,我只选择了 stringbuf。直接从 std::streambuf 继承时的行为是相同的。你能详细说明你的意思吗?
  • std::streambuf 提供了一个接口,用于缓冲访问其他地方的字符序列(RAM、文件、TCP 流......)。但标准并未指定使用多少缓冲。
  • 是的,我知道,我在为 tcp 套接字处理自定义 std::streambuf 时注意到了这种行为。在 libc++ 中过早调用 underflow,这可能会无缘无故地导致非常长的块。
  • 也许它有助于使用 std::streambuf::pubsetbuf 设置更大的缓冲区。不要忘记检查返回值是否为非空,并在 std::streambuf 对象的生命周期后删除该缓冲区。我从来没有尝试过,所以我不知道它是否有帮助,是否还有其他陷阱。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-13
  • 2011-09-15
相关资源
最近更新 更多