bug-commoncpp
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

C++ exceptions in persistent streams (finally)


From: erik_ohrnberger
Subject: C++ exceptions in persistent streams (finally)
Date: Wed, 1 Feb 2006 16:05:25 -0500

/*
Below is a test program that I wrote to try and discern how exceptions work
when persistent streams encounter errors.

The bottom line is that you can pretty much ignore any sort of exception
support in the persistent streams package.  From what I've been able to find
out, it will never throw any exceptions from the various read and write
methods.

So you are left to try and use the standard C++ library iostreams for
exceptions, except, they appear to not implement them in compliance with the
ISO specifications either (see
http://gcc.gnu.org/onlinedocs/libstdc++/ext/lwg-defects.html#211).
Although, this is for reading strings while the persistent stream is reading
binary, so this may not apply.

What I did find out is that you can make use of exceptions, but you have to
check the state of the file stream, figure out which issue is the problem,
and throw a PersistException in your low level code.  Then you high lever
code can actually use the appropriate catch clauses to handle the throw
exceptions.  Not pretty, but I guess it'll do for now.  I'm just hoping that
this will end up helping someone out there, as I've asked about this a
number of times and really didn't receive very many responses.

The test program below is what I used to selectively comment out specific
statements and parts, run, and record the results.  It should be nothing
more than a copy/paste operation into your favorite editor to get it being
useful for you.

Software versions:
gcc --version:  gcc (GCC) 3.3.6 (Gentoo 3.3.6, ssp-3.3.6-1.0, pie-8.7.8)
libstdc++:              as released as part of gcc above
commoncpp2:             1.3.1
*/

#include <errno.h>
#include <fstream>
#include <cc++/persist.h>
using namespace std;
using namespace ost;
int main( int argc, char** argv )
{
        set_terminate( __gnu_cxx::__verbose_terminate_handler );
        const char*                     cFileName       = "exception.obst";
        const int                       cIterm          = 10;

        // write out a stream
        fstream         outputArchive(  cFileName, ios::out | ios::binary );
        Engine          outputEngine(   outputArchive, Engine::modeWrite );

        for( int i = 0; i < cIterm; i++ )
        {
                outputEngine << i;
        }
        outputArchive.close();

        // Read in the stream expecting an exception (we are reading N+1
items)
        try
        {
                // Automatic scope instance DTOR closes file, exception or
not.
                fstream         inputArchive(   cFileName, ios::in |
ios::binary );

                // If we use this, it'll cause a core dump and no exception
handling
                // This according to:
http://www.cplusplus.com/ref/iostream/ios/exceptions.html
                //inputArchive.exceptions( fstream::eofbit |
fstream::failbit | fstream::badbit );
                // which results in core dump after the extraction to int

                // However, according to:
                //
http://gcc.gnu.org/onlinedocs/libstdc++/ext/lwg-defects.html#211
                // at one time, extracting at end of file didn't set the
failbit, but
                // should now.  So how come we get a core dump?

                // Interestingly, on:
http://gcc.gnu.org/onlinedocs/libstdc++/17_intro/CHECKLIST
                // it shows that ios_base::exceptions( arg ) status as
missing(!?)

                // If we use:
                inputArchive.exceptions( fstream::badbit );
                // exception caught, but no info (unless we enable it by
checking inputArchive flags

                //inputArchive.exceptions( fstream::eofbit );
                // results in core dump after the extraction to int

                //inputArchive.exceptions( fstream::failbit );
                // results in core dump after the extraction to int

                //inputArchive.exceptions( fstream::badbit | fstream::eofbit
);
                // results in core dump after the extraction to int

                //inputArchive.exceptions( fstream::badbit |
fstream::failbit );
                // results in core dump after the extraction to int

                Engine          inputEngine(    inputArchive,
Engine::modeRead );
                for( int i = 0; i < cIterm + 1; i++ )
                {
                        string  err;
                        int     data;
                        inputEngine >> data;
                        err = strerror( errno );

                        if( !inputArchive.good() )
                        {
#if 1
                                // If we don't use this, we get no deails.
                                if( inputArchive.eof() )
                                        err = "eof hit";
                                if( inputArchive.bad() )
                                        err = "bad stream state";
                                if( inputArchive.fail() )
                                        err = "extraction failed";
#endif
                                // if we don't do this, we get no exception
thrown, and read an item 10
                                // so we can throw either of these.
                                //throw ios::failure( err.c_str() );
                                throw PersistException( err.c_str() );
                        }
                        cout << "read item: " << i << endl;
                }
        }
        // catches, from most specific to most general.
        catch( Engine::Exception& e )                   // persist Engine
exception
        {
                cout << "Engine::Exception caught! " << e.getString() <<
endl;
        }
        catch( PersistException& e )                    // Persist Exception
        {
                cout << "PersistException caught! " << e.getString() <<
endl;
        }
        catch( Exception& e )                                   //
ost::Exception
        {
                cout << "Exception caught! " << e.getString() << endl;
        }
        catch( ios::failure& e )                                //
ios:exception
        {
                cout << "ios::failure exception caught! " << e.what() <<
endl;
        }
        catch( exception e )                                    // general
library exception
        {
                cout << "std::exception caught! " << e.what() << endl;
        }
#endif
        return 0;
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]