c++ file bad bit - c++

when I run this code, the open and seekg and tellg operation all success.
but when I read it, it fails, the eof,bad,fail bit are 0 1 1.
What can cause a file bad?
thanks
int readriblock(int blockid, char* buffer)
{
ifstream rifile("./ri/reverseindex.bin", ios::in|ios::binary);
rifile.seekg(blockid * RI_BLOCK_SIZE, ios::beg);
if(!rifile.good()){ cout<<"block not exsit"<<endl; return -1;}
cout<<rifile.tellg()<<endl;
rifile.read(buffer, RI_BLOCK_SIZE);
**cout<<rifile.eof()<<rifile.bad()<<rifile.fail()<<endl;**
if(!rifile.good()){ cout<<"error reading block "<<blockid<<endl; return -1;}
rifile.close();
return 0;
}

Quoting the Apache C++ Standard Library User's Guide:
The flag std::ios_base::badbit indicates problems with the underlying stream buffer. These problems could be:
Memory shortage. There is no memory available to create the buffer, or the buffer has size 0 for other reasons (such as being provided from outside the stream), or the stream cannot allocate memory for its own internal data, as with std::ios_base::iword() and std::ios_base::pword().
The underlying stream buffer throws an exception. The stream buffer might lose its integrity, as in memory shortage, or code conversion failure, or an unrecoverable read error from the external device. The stream buffer can indicate this loss of integrity by throwing an exception, which is caught by the stream and results in setting the badbit in the stream's state.
That doesn't tell you what the problem is, but it might give you a place to start.
Keep in mind the EOF bit is generally not set until a read is attempted and fails. (In other words, checking rifile.good after calling seekg may not accomplish anything.)
As Andrey suggested, checking errno (or using an OS-specific API) might let you get at the underlying problem. This answer has example code for doing that.
Side note: Because rifile is a local object, you don't need to close it once you're finished. Understanding that is important for understanding RAII, a key technique in C++.

try old errno. It should show real reason for error. unfortunately there is no C++ish way to do it.

Related

Correct way of reading /proc/pid/status

I read /proc/<pid>/status this way:
std::ifstream file(filename);
std::string line;
int numberOfLinesToRead = 4;
int linesRead = 0;
while (std::getline(file, line)) {
// do stuff
if (numberOfLinesToRead == ++linesRead) {
break;
}
}
I noticed that in rare cases std::getline hangs.
Why it happens? I was under impression that proc filesystem should be in somewhat consistent state and there should not be cases when newline is missing. My assumption was that getline returns false when EOF/error occurs.
What is the recommended, safe way to read /proc/<pid>/status ?
Perhaps a more sure path is to use fread into a large buffer. The status file is small so allocate a local buffer and read the whole file.
Example look at the second answer for the simplest solution
This may still fail on the fopen or fread but a sensible error should be returned.
/proc is a virtual filesystem. That means reading from "files" in it is not the same as reading from normal filesystem.
If process exits the information about it is removed from /proc much faster than if it was real filesystem (dirty cache flushing delay involved here).
Bearing that in mind imagine that process exits before you get to read next line which wasn't buffered yet.
The solution is either to account for file loss since you may not need information about process which does not exists anymore or buffer the entire file and then only parse it.
EDIT: the hang in process should clearly be related to the fact that this is virtual filesystem. It does not behave exactly same way as real filesystem. Since this is specific fs type the issue could be in fs driver. The code you provide looks fine for normal file reading.

Valgrind says about "Invalid write" in fclose()

I created a stream using fmemopen(). I am closing it with fclose() and freeing the buffer after reading. Valgrind reports about problem at fclose() line:
==9323== Invalid write of size 8
==9323== at 0x52CAE52: _IO_mem_finish (memstream.c:139)
==9323== by 0x52C6A3E: fclose##GLIBC_2.2.5 (iofclose.c:63)
==9323== by 0x400CB6: main (main.cpp:80)
==9323== Address 0xffefffa80 is just below the stack ptr. To suppress,
use: --workaround-gcc296-bugs=yes
What's happening? Maybe fclose() cannot properly close a memory stream? Or maybe valgrind worries without reason and I can ignore that?
As you haven't posted your code, the following is pure speculation. You're probably writing more output to the stream than you promised to when you opened it. Did you account for the final NUL (if you didn't open with "b")?
Did you read the following in the manual page?
When a stream that has been opened for writing is flushed (fflush(3)) or closed (fclose(3)), a null byte is written at the end of the buffer if there is space. The caller should ensure that an extra byte is available in
the buffer (and that size counts that byte) to allow for this.
Attempts to write more than size bytes to the buffer result in an error. (By default, such errors will be visible only when the stdio buffer is flushed. Disabling buffering with setbuf(fp, NULL) may be useful to detect
errors at the time of an output operation. Alternatively, the caller can explicitly set buf as the stdio stream buffer, at the same time informing stdio of the buffer's size, using setbuffer(fp, buf, size).)
Following the latter advice should reveal the write that is exceeding the capacity.
It was my fault. I wrote that I use fmemopen() to open a stream, but this code wasn't running, and I get stream, produced earlier with open_memstream(). Although this stream was opened for writing, I can read from it. However valgrind reports about problem. I fixed my code, valgrind find no errors.

What could cause a stream to enter the "bad" state?

In C++, each stream has a bad bit:
This flag is set by operations performed on the stream when an error occurs while read or writing data, generally causing the loss of integrity of the stream.
Source
What would cause a stream to "lose integrity" and enter the bad state? This is not the same as the fail state, which most often occurs when an input stream attempts to store a value into a variable that cannot accept said value (such as attempting to store a string into an integer variable).
Note that this question is a more general form of c++ file bad bit, which is specific to file input streams; this question is not an exact duplicate as it applies to both input and output streams in general.
According to cppreference.com :
The standard library sets badbit in the following situations:
Insertion into the output stream by put() or write() fails for any
reason.
Insertion into the output stream by operator<<, std::put_money or
std::put_time, could not complete because the end of the output
stream was reached (The facet's formatting output function such as
num_put::put() or money_put::put(), returns an iterator iter such
that iter.failed()==true)
Stream is constructed with a null pointer for rdbuf(), or
putback()/unget() is called on a stream with a null rdbuf(), or a
null pointer passed to operator<<(basic_streambuf*)
rdbuf()->sputbackc() or rdbuf()->sungetc() return traits::eof() to
putback() orunget()`
rdbuf()->pubsync() returns -1 to sync(), to flush(), or to the
destructor of ostream::sentry on a unitbuf stream
Exception is thrown during an I/O operation by any member function of
the associated stream buffer (e.g. sbumpc(), xsputn(), sgetc(),
overflow(), etc)
Exception is thrown in iword() or pword() (e.g. std::bad_alloc)
This may be one more reason to choose cppreference.com over www.cpluplus.com, see:
What's wrong with cplusplus.com?
Take a look at the Apache C++ Standard Library User's Guide. Two potential causes for a badbit are listed there. I quote:
Memory shortage: There is no memory available to create the buffer, or the buffer has size 0 for other reasons (such as being provided from outside the stream), or the stream cannot allocate memory for its own internal data.
The underlying stream buffer throws an exception: The stream buffer might lose its integrity, as in memory shortage, or code conversion failure, or an unrecoverable read error from the external device. The stream buffer can indicate this loss of integrity by throwing an exception, which is caught by the stream and results in setting the badbit in the stream's state.

How the functions overflow and underflow of basic_streambuf wok

I'm reading the C++ 11 standard. The sections 27.6.3.4.3/7 and 27.6.3.4.5/3 describe the functions "int_type underflow();" and "int_type overflow(int_type c = traits::eof());". There is no example to explain how they work. Can somebody help to explain the functions with the example?
The basic idea is pretty simple. underflow is used for input streams. When there's no data left in the input buffer, underflow is called to read data from the actual source (e.g., file or socket) to at least partially refill the buffer.
overflow is pretty much the opposite -- when a buffer is full, overflow is called to write the data out to the associated file or socket, or whatever. It's also called to flush the buffer just before an output stream is destroyed.

ifstream operator >> and error handling

I want to use ifstream to read data from a named piped. I would like to use its operator>> to read formatted data (typically, an int).
However, I am a bit confused in the way error handling works.
Imagine I want to read an int but only 3 bytes are available. Errors bits would be set, but what will happen to theses 3 bytes ? Will they "disappear", will they be put back into the stream for later extraction ?
Thanks,
As has been pointed out, you can't read binary data over an istream.
But concerning the number of available bytes issue (since you'll
probably want to use basic_ios<char> and streambuf for your binary
streams): istream and ostream use a streambuf for the actual
sourcing and sinking of the bytes. And streambuf normally buffer: the
procedure is: if a byte is in the buffer, return it, otherwise, try to
reload the buffer, waiting until the reloading has finished, or
definitively failed. In case of definitive failure, the streambuf
returns end of file, and that terminates the input; istream will
memorize the end of file, and not attempt any more input. So if the
type you are reading needs four bytes, it will request four bytes from
the streambuf, and will normally wait until those four bytes are
there. No error will be set (because there isn't an error); you will
simply not return from the operator>> until those four bytes arrive.
If you implement your own binary streams, I would strongly recommend
using the same pattern; it will allow direct use of already existing
standard components like std::ios_base and (perhaps) std::filebuf,
and will provide other programmers with an idiom they are familiar with.
If the blocking is a problem, the simplest solution is just to run the
input in a separate thread, communicating via a message queue or
something similar. (Boost has support for asynchronous IO. This avoids
threads, but is globally much more complicated, and doesn't work well
with the classical stream idiom.)