Error with ifstream and exceptions

M

Marco

Hi,

in the following code I get an error message after the file is output. What
did I do wrong?

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main() {
ifstream fileIn;
fileIn.exceptions ( ifstream::failbit | ifstream::badbit );
try {
fileIn.open( "file" ); }
catch ( ifstream::failure e ) {
cout << "Error."; }

string line;
while ( getline( fileIn, line ) ) {
cout << line << endl;
}
fileIn.close();
return 0;
}

The error message after the output of »file« is:

terminate called after throwing an instance of 'std::ios_base::failure'
what(): basic_ios::clear
Aborted


Regards
Marco
 
J

Jonathan Lee

in the following code I get an error message after the file is output. What
did I do wrong?

The "while" line is the culprit:
  while ( getline( fileIn, line ) ) {
    cout << line << endl;
  }

specifically, it continues to execute until the result of getfile(),
i.e.,
fileIn, evaluates to false. This happens via ios::eek:perator void*(),
which
will be NULL (false for the purposes of the while) exactly when
failbit
or badbit is set. But you told it to throw an exception when these
bits
are set, so the while loop doesn't terminate properly. The exception
gets
thrown first.

BTW, the whole operator void*() thing is explained here:
http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.4

--Jonathan
 
M

Marco

The "while" line is the culprit:


specifically, it continues to execute until the result of getfile(),
i.e.,
fileIn, evaluates to false. This happens via ios::eek:perator void*(),
which
will be NULL (false for the purposes of the while) exactly when
failbit
or badbit is set.

This is the behaviour I expected.
But you told it to throw an exception when these
bits
are set, so the while loop doesn't terminate properly. The exception
gets
thrown first.

Why does it throw an exception? The while block is outside of the try block.
Sorry, maybe this is a stupid question, I'm a beginner in C++. But I expected
exceptions only to be thrown in the try block. What else is it for?
BTW, the whole operator void*() thing is explained here:
http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.4

Thanks for the link.


Regards
Marco
 
I

Ian Collins

This is the behaviour I expected.


Why does it throw an exception?

You told it to.
The while block is outside of the try block.

That isn't relevant, exceptions can be thrown anywhere.
Sorry, maybe this is a stupid question, I'm a beginner in C++. But I expected
exceptions only to be thrown in the try block. What else is it for?

To catch exceptions thrown within it.
 
P

Paul

Ian Collins said:
You told it to.


That isn't relevant, exceptions can be thrown anywhere.
Ian Collins obviously doesn't know how to answer the question properly.
I don't know how to answer the question but I know enough to get by.
Ian is different from most of the other arseholes around here because he is
obviously the most clueless of them all.
To catch exceptions thrown within it.

Ian obvioulsy gets confused between the try block and the catch block. :)
 
M

Marco

Ian Collins obviously doesn't know how to answer the question properly.
I don't know how to answer the question but I know enough to get by.
Ian is different from most of the other arseholes around here because he is
obviously the most clueless of them all.


Ian obvioulsy gets confused between the try block and the catch block. :)

I'm confused, too. Exceptions can be thrown everywhere, is that right? But
what is the purpose of the try block? Why isn't it enough to write a catch
block if the exceptions can be thrown in the try block and outside the try
block? (I know it's not valid to write catch without try, it's just to
understand how things work.)


Regards
Marco
 
P

Paul

Marco said:
I'm confused, too. Exceptions can be thrown everywhere, is that right? But
what is the purpose of the try block? Why isn't it enough to write a catch
block if the exceptions can be thrown in the try block and outside the try
block? (I know it's not valid to write catch without try, it's just to
understand how things work.)
Yeah Exceptions can be thrown anytime.
A try block is used to enclose a piece of code that you think might possibly
throw an exception, for example opening a file. You can either re-throw the
exception or catch the exception that has been thrown from within a try
block.
Exceptions can be thrown by the OS or from code, there are different types
of exceptions. Your try/catch block is looking for an exception to be thrown
by the OS on file.open but this doesn't happen. A C++ exception is thrown in
the while loop and this is not handled inside a try block.
I think any code that can possibly invoke a C++ throw( C++ Exception) must
be enclosed in a try block, but not 100% sure, try putting the while loop in
a try/catch block and see what happens. :)
..

HTH
 
M

Marco

Yeah Exceptions can be thrown anytime.
A try block is used to enclose a piece of code that you think might
possibly throw an exception, for example opening a file. You can either
re-throw the exception or catch the exception that has been thrown from
within a try block.
Exceptions can be thrown by the OS or from code, there are different types
of exceptions. Your try/catch block is looking for an exception to be
thrown by the OS on file.open but this doesn't happen. A C++ exception is
thrown in the while loop and this is not handled inside a try block.
I think any code that can possibly invoke a C++ throw( C++ Exception) must
be enclosed in a try block, but not 100% sure, try putting the while loop
in a try/catch block and see what happens. :)

Thanks for your explanation. That make things more clear to me. I tried the
following:

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main() {
ifstream fileIn;
fileIn.exceptions ( ifstream::failbit | ifstream::badbit );
try {
fileIn.open( "file" ); }
catch ( ifstream::failure e ) {
cout << "Error."; }

string line;
try {
while ( getline( fileIn, line ) ) {
cout << line << endl;
}
}
catch (...) {}

fileIn.close();
return 0;
}

It works. But looking at this code other questions arise. Is this the
preferred way to do it? Can I stop exceptions to be thrown, since I don't know
which code might possibly throw an excetion. I think about something like

fileIn.exceptions ( none );

after the (first) catch block. That way I don't have to put everything that
might throw an exception in a try block, to make my code more readable.


Regards
Marco
 
J

Jonathan Lee

I'm confused, too. Exceptions can be thrown everywhere, is that right? But
what is the purpose of the try block? Why isn't it enough to write a catch
block if the exceptions can be thrown in the try block and outside the try
block? (I know it's not valid to write catch without try, it's just to
understand how things work.)

Regards
Marco

Hi Marco,
as others have mentioned, an exception can be thrown anywhere. The
purpose
of the try/catch structure is to indicate where you are interested in
responding to exceptions (try), and what you're going to do when one
occurs
(catch).

In the example you posted, for instance, you respond to
ifstream::failure
exceptions by printing a message. All other exceptions are left
unhandled
by your code, and continue with the default behavior (stack
unwinding).

The reason you might do this is that some exceptions may be
"expected".
Or perhaps its better to say some exceptions can be recovered from.
Like reading from a file might suddenly fail if the file were on a
network
and someone kicked out the network cable. When the file can't be read
from,
your program may be able to continue by simply printing a message to
the
user and quitting from operating on the file.

On the other hand, if while reading from that file the OS runs out
of
memory, the program probably can't continue. So you don't catch it;
you
let the exception propagate until it terminates your program.

--Jonathan
 
P

Paul

Marco said:
Thanks for your explanation. That make things more clear to me. I tried
the
following:

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main() {
ifstream fileIn;
fileIn.exceptions ( ifstream::failbit | ifstream::badbit );
try {
fileIn.open( "file" ); }
catch ( ifstream::failure e ) {
cout << "Error."; }

string line;
try {
while ( getline( fileIn, line ) ) {
cout << line << endl;
}
}
catch (...) {}

fileIn.close();
return 0;
}

It works. But looking at this code other questions arise. Is this the
preferred way to do it? Can I stop exceptions to be thrown, since I don't
know
which code might possibly throw an excetion. I think about something like

fileIn.exceptions ( none );

after the (first) catch block. That way I don't have to put everything
that
might throw an exception in a try block, to make my code more readable.
It depends what you are doing.
Many code examples only use try block around the file.open part, so they
only want to stop the program from crashing in the event of a file.open
error.
Removing "fileIn.exceptions ( ifstream::failbit | ifstream::badbit );" might
solve your problem.

I would check a few online tutorials and examples , there loads of them
about file streams. Choose the option that suits you best.
 
J

Juha Nieminen

Paul said:
Yeah Exceptions can be thrown anytime.

I like how you first insult Ian, and then proceed in your next post to
give the exact same answer he did. Way to go.
 
M

Marco

Many code examples only use try block around the file.open part, so they
only want to stop the program from crashing in the event of a file.open
error.

That's exactly what I want. I tried (see my first post), but it didn't work.
Removing "fileIn.exceptions ( ifstream::failbit | ifstream::badbit );"
might solve your problem.

I also tried it. The following code doesn't throw an exception.


#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main() {
ifstream fileIn;
try {
fileIn.open( "not_existent" ); }
catch ( ... ) {
// This never gets output
cout << "Error."; }

string line;
// while loop works okay now
while ( getline( fileIn, line ) ) {
cout << line << endl; }

fileIn.close();
return 0;
}

I would check a few online tutorials and examples , there loads of them
about file streams. Choose the option that suits you best.

I did, but there are many solutions that are considered bad practice. I don't
know yet how to do it the right way. What I try seems a bit verbose to me.

The following does what I want (and is pretty short, too):

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main() {
ifstream fileIn;
fileIn.open( "not_existent" );
if ( !fileIn )
cout << "Error." << endl;

string line;
while ( getline( fileIn, line ) ) {
cout << line << endl; }

fileIn.close();
return 0;
}

But I've read that this is C-like, not C++ and I should better use exceptions
to handle non-existent files. That's what I tried.

I thought I'm overseeing the obvious, but I think I used the wrong approach.


Regards
Marco
 
M

Marco

Hi Marco,
as others have mentioned, an exception can be thrown anywhere. The
purpose
of the try/catch structure is to indicate where you are interested in
responding to exceptions (try), and what you're going to do when one
occurs
(catch).

In the example you posted, for instance, you respond to
ifstream::failure
exceptions by printing a message. All other exceptions are left
unhandled
by your code, and continue with the default behavior (stack
unwinding).

The reason you might do this is that some exceptions may be
"expected".
Or perhaps its better to say some exceptions can be recovered from.
Like reading from a file might suddenly fail if the file were on a
network
and someone kicked out the network cable. When the file can't be read
from,
your program may be able to continue by simply printing a message to
the
user and quitting from operating on the file.

On the other hand, if while reading from that file the OS runs out
of
memory, the program probably can't continue. So you don't catch it;
you
let the exception propagate until it terminates your program.

Thanks for the explanation. It helped me understanding better how exceptions
work.


Regards
Marco
 
P

Paul

Marco said:
That's exactly what I want. I tried (see my first post), but it didn't
work.


I also tried it. The following code doesn't throw an exception.


#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main() {
ifstream fileIn;
try {
fileIn.open( "not_existent" ); }
catch ( ... ) {
// This never gets output
cout << "Error."; }

string line;
// while loop works okay now
while ( getline( fileIn, line ) ) {
cout << line << endl; }

fileIn.close();
return 0;
}



I did, but there are many solutions that are considered bad practice. I
don't
know yet how to do it the right way. What I try seems a bit verbose to me.

The following does what I want (and is pretty short, too):

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main() {
ifstream fileIn;
fileIn.open( "not_existent" );
if ( !fileIn )
cout << "Error." << endl;

string line;
while ( getline( fileIn, line ) ) {
cout << line << endl; }

fileIn.close();
return 0;
}

But I've read that this is C-like, not C++ and I should better use
exceptions
to handle non-existent files. That's what I tried.

I thought I'm overseeing the obvious, but I think I used the wrong
approach.
It depends on the purpose of the program, how critical it is and how much
control you want.
The problem with both your programs is that you check incase the file handle
is null , but you don't abort if it is.
If you use a simple 'if' statement then you should construct your code in
such a way that...
if(filehandle is good){ do stuff}
else{ output error and abort }

It depends on the purpose and how critical your program is. If you are just
creating small test porgrams then its fine to not bother with error checking
at all. I like to always wrap file ops in an if statement, even in trivial
programs, as I think its good practise. I'd actually put file ops inside a
function and do something like:
if(filehandle) { fileOpsFunction( filehandle); }
It keeps your main() function cleaner and easier to read. I put almost
everything in functions. :)

HTH
 
M

Marco

It depends on the purpose of the program, how critical it is and how much
control you want.

I start writing C++ programs and I want to start with a good programming style
from the scratch.
The problem with both your programs is that you check incase the file
handle is null , but you don't abort if it is.

It's not a problem. For demonstration I removed everything that is not really
necessary to understand my problem. I abort if the file is not found in the
real program.
If you use a simple 'if' statement then you should construct your code in
such a way that...
if(filehandle is good){ do stuff}
else{ output error and abort }

It depends on the purpose and how critical your program is. If you are just
creating small test porgrams then its fine to not bother with error
checking at all. I like to always wrap file ops in an if statement, even in
trivial programs, as I think its good practise. I'd actually put file ops
inside a function and do something like:
if(filehandle) { fileOpsFunction( filehandle); }
It keeps your main() function cleaner and easier to read. I put almost
everything in functions. :)

It is included in a function. I just removed all unnecessary stuff to make the
code as easy as possible.

But one question is still open: Is it possible to do something like:

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main() {
ifstream fileIn;
fileIn.exceptions ( ifstream::failbit | ifstream::badbit );
try {
fileIn.open( "file" ); }
catch ( ifstream::failure e ) {
cout << "Error."; }
fileIn.exceptions ( none ); // Switch exceptions off

string line;
while ( getline( fileIn, line ) ) {
cout << line << endl;
}
fileIn.close();
return 0;
}

I mean to switch the exceptions off again after having switched them on before
to avoid that the while loop is able to throw an exception?


Regards
Marco
 
P

Paul

Marco said:
I start writing C++ programs and I want to start with a good programming
style
from the scratch.


It's not a problem. For demonstration I removed everything that is not
really
necessary to understand my problem. I abort if the file is not found in
the
real program.


It is included in a function. I just removed all unnecessary stuff to make
the
code as easy as possible.

But one question is still open: Is it possible to do something like:

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main() {
ifstream fileIn;
fileIn.exceptions ( ifstream::failbit | ifstream::badbit );
try {
fileIn.open( "file" ); }
catch ( ifstream::failure e ) {
cout << "Error."; }
fileIn.exceptions ( none ); // Switch exceptions off

string line;
while ( getline( fileIn, line ) ) {
cout << line << endl;
}
fileIn.close();
return 0;
}

I mean to switch the exceptions off again after having switched them on
before
to avoid that the while loop is able to throw an exception?
I'm not sure I haven't used exception masking before. I think it can be
done. A quick web search suggests to me that :
"By default, stream objects have a goodbit exception mask, which means no
exceptions are thrown when any of the state flags is set."
ref: http://www.cplusplus.com/reference/iostream/ios/exceptions/

I would try fileIn.exceptions( ifstream::goodbit);

And see it that helps.
 
B

Bo Persson

Marco said:
I start writing C++ programs and I want to start with a good
programming style from the scratch.


It's not a problem. For demonstration I removed everything that is
not really necessary to understand my problem. I abort if the file
is not found in the real program.


It is included in a function. I just removed all unnecessary stuff
to make the code as easy as possible.

But one question is still open: Is it possible to do something like:

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main() {
ifstream fileIn;
fileIn.exceptions ( ifstream::failbit | ifstream::badbit );
try {
fileIn.open( "file" ); }
catch ( ifstream::failure e ) {
cout << "Error."; }
fileIn.exceptions ( none ); // Switch exceptions off

string line;
while ( getline( fileIn, line ) ) {
cout << line << endl;
}
fileIn.close();
return 0;
}

I mean to switch the exceptions off again after having switched
them on before to avoid that the while loop is able to throw an
exception?

But here the open() functions is not likely to throw any exceptions of
the kind you try to catch. Open() returns NULL if it cannot open the
file (which is not considered exceptional).

The only exception I would expect is std::bad_alloc if you are totally
out of memory. In that case, writing to std::cout is likely not to
work either (perhaps causing another bad_alloc). :-(



Bo Persson
 
M

Marco

But here the open() functions is not likely to throw any exceptions of
the kind you try to catch.

Yes, it is.
Open() returns NULL if it cannot open the file (which is not considered
exceptional).

open() is defined as:

void open ( const char * filename, ios_base::eek:penmode mode = ios_base::in );

and it will never return NULL, if I'm not mistaken. One can check the ifstream
after open() as I suggested in an earlier post.


Regards
Marco
 
J

Joshua Maurice

I'm confused, too. Exceptions can be thrown everywhere, is that right? But
what is the purpose of the try block? Why isn't it enough to write a catch
block if the exceptions can be thrown in the try block and outside the try
block? (I know it's not valid to write catch without try, it's just to
understand how things work.)

Contrary to the other posters in this thread, C++ exceptions cannot be
thrown from anywhere.

In short, a C++ exception can only result from an executed "throw"
statement or or a failed dynamic_cast<reference_type>. (IIRC, those
are the only two things.)

C++ exceptions can also be thrown from standard library functions and
classes, such as std::vector, and from language features, such as the
new operator. However, these are likely implemented using "throw"
statements, and that's the better way to think about it. (Yes yes. I
know they don't have to be. Standard library functions and features
can be implemented whatever silly way they want. That's why I
specifically called them out.)

In practice, because of the widespread use of such features, it's
almost as if exceptions can come from anywhere, but C++ exceptions are
synchronous - they only come from a very specific set of things which
can throw.

If you want to talk about asynchronous exceptions, or exceptions from
null pointer accesses (such as what Visual Studios did by default in
older versions), then you're no longer talking about standard C++, and
you ought to consult those newsgroups and those documents instead.

Now, on to your question. Consider the code:

#include <iostream>
using namespace std;
int main()
{ try
{ try
{ throw 1;
}catch (... )
{ cout << 2 << endl;
throw 3;
}
}catch (... )
{ cout << 4 << endl;
}
throw 5;
}

Every catch block has exactly one associated try block. The reason is
that the catch block will only be invoked on exceptions thrown from
within that try block. For example, in the above code, throw 1 will
throw an exception from within a try block. That try block has an
associated catch block which matches the thrown exception (... matches
all exceptions), so that catch block will be executed. 2 is printed.
That catch block during execution executes another throw statement,
throw 3, which will throw a new exception. That new exception is
inside a different try block with an associated matching catch block,
so that associated catch block will be executed. 4 is printed.
Finally, control flows past the end of that catch block, and it hits
the throw 5 statement. This throw is outside of any try block, so it
is not caught, and so the program dies.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top