Bug in std::streambuf::in_avail ??

The following code:

std::stringstream test;
std::streamsize dataSize;

test << "";
dataSize = test.rdbuf()->in_avail();
cout << "Available character: " << dataSize << ", while using string: " << test.str() << std::endl;

test << "A";
dataSize = test.rdbuf()->in_avail();
cout << "Available character: " << dataSize << ", while using string: " << test.str() << std::endl;

test << " bigger string";
dataSize = test.rdbuf()->in_avail();
cout << "Available character: " << dataSize << ", while using string: " << test.str() << std::endl;

Outputs this:

Available character: 0, while using string:
Available character: 1, while using string: A
Available character: 1, while using string: A bigger string

However, according to: http://www.cplusplus.com/reference/streambuf/streambuf/in_avail/

The last output should indicate that the stringstream is 15 character long.

Is this a bug in gcc (I am using 5.4.0 in Ubuntu 16.04)
last output should indicate that the stringstream is 15 character long.

It is not what that function does: it reports the size of the get area (meaning, how many bytes can be read without making a virtual call). Only if the get area is empty it dispatches to showmanyc which returns the non-blocking size of the data source (for those data sources that support non-blocking sizes).

By calling in_avail, you are effectively probing the get area pointer update policy: make your "bigger string" one byte bigger, and you'll see that the second write updates the get area in GNU libstdc++ used here https://wandbox.org/permlink/xBAmMIqxMXUQGNPz (but not in LLVM libc++ or MSVC - they need an even bigger string: https://wandbox.org/permlink/adXZLv2T48AqFNhX and http://rextester.com/CJMQ17171 ).

The reason for this behavior is that your second write didn't trip overflow because the underlying string capacity wasn't exceeded. Without a virtual function call, there is no way for a write to touch the read-side of a stream.
Last edited on
Not sure what "get area" is or means. Not sure either what "can be read without making a virtual call" means.

In nay case, I updated the code by adding this:

test << " - Even a bigger string";
dataSize = test.rdbuf()->in_avail();
cout << "Available character: " << dataSize << ", while using string: " << test.str() << std::endl;


and I get:

Available character: 1, while using string: A bigger string - Even a bigger string
In any case, if I actually get the data, I do get the correct number of characters.

char buffer[1024];
dataSize = test.rdbuf()->sgetn(buffer, 1024);
cout << "Got: " << dataSize << " characters" << std::endl;

Since I get this output:

Got: 26 characters


Also, the reference to www.cpluplus.com says this:

`The number of characters available to read.`

Is this statement wrong?
Not sure what "get area" is or means. Not sure either what "can be read without making a virtual call" means.

If you're going to be calling member functions of std::streambuf, you should read up on what that class does and why. cppreference has a fairly detailed summary: http://en.cppreference.com/w/cpp/io/basic_streambuf

the reference to www.cpluplus.com says this:

`The number of characters available to read.`

Is this statement wrong?

On its own, yes, but cplusplus.com continues on to clarify "The function returns the number of characters directly available at the get pointer before the end pointer (i.e., it returns (egptr()-gptr()) without calling any virtual member function"
Last edited on
Ok, so, is it fair to say:

- if a stream has data, but the data is not buffered in an object (gptr here) accessible from the base class (basic_streambuf here) then in_avail() will return 0
- because of the above, there is no way to know ahead of time if:
- there is data
- how many data may be present

So, what is the purpose of in_avail(). Gets (sgetn here) may return more data than what in_avail() reports and in_avail() may report no data when in fact there is. When would in_avail() be useful?
if a stream has data, but the data is not buffered in an object (gptr here) accessible from the base class (basic_streambuf here) then in_avail() will return 0

no, in_avail() will call showmanyc in that case. It's the second paragraph of the description in the page you linked.

clauderobi wrote:
When would in_avail() be useful?

When you're working with a stream associated with a blocking character source (such as a TCP stream) whose author included meaningful support for the "readsome" operation. Like the majority of I/O streams functionality, it is aimed at the programmers that are writing their own buffers and streams, not at the programmers that use the standard library (time appears to have proven this to be an unsuccessful design goal: the almost-standard tcp::iostream doesn't support it)
Last edited on
Topic archived. No new replies allowed.