basic_filebuf issues

This is a discussion on basic_filebuf issues within the C++ Programming forums, part of the General Programming Boards category; I'm working on a couple classes that, when finished, will allow binary I/O to files, strings, etc. Basic usage is: ...

  1. #1
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902

    Question basic_filebuf issues

    I'm working on a couple classes that, when finished, will allow binary I/O to files, strings, etc. Basic usage is:
    Code:
    mystream << binaryio::little_endian << binaryio::set_size(2) << my_integer;
    So far, it's working wonderfully for strings. I plugged in the bit of code needed for file I/O, and everything crashed. I've boiled it down to the following small example:
    Code:
    #include <fstream>
    #include <iostream>
    
    int main()
    {
    	unsigned char data[8];
    	
    	std::basic_filebuf<unsigned char, std::char_traits<unsigned char> > bfs;
    	
    	std::cerr << "About to open file..." << std::endl;
    	bfs.open("filetest", std::ios::in | std::ios::binary);
    	
    	std::cerr << "Is file open? " << (bfs.is_open() ? "yes" : "no") << std::endl;
    	std::cerr << "Attempting read of 8 bytes." << std::endl;
    	
    	try
    	{
    		std::streamsize ret;
    		ret = bfs.sgetn(data, 8);
    		std::cerr << "Got " << ret << " bytes." << std::endl;
    	}
    	catch(std::exception &e)
    	{
    		std::cerr << "Exception: " << e.what() << std::endl;
    		return 1;
    	}
    	return 0;
    }
    The program says that the file is open, and will get to the "Attempting read of 8 bytes" part, call basic_filebuf::sgetn(), and a "St8bad_cast" exception gets thrown. On my system, the backtrace at the time of the exception looks something like this:
    Code:
    std::__check_facet(NULL)
       in bits/localefwd.h:187
    std::basic_filebuf<unsigned char, std::char_traits<unsigned char> >::underflow()
    std::basic_filebuf<unsigned char, std::char_traits<unsigned char> >::uflow()
    std::basic_filebuf<unsigned char, std::char_traits<unsigned char> >::xsgetn()
    std::basic_filebuf<unsigned char, std::char_traits<unsigned char> >::xsgetn()
    std::basic_filebuf<unsigned char, std::char_traits<unsigned char> >::sgetn()
    main()
    Looking at the __check_facet function, all it does is check if it's parameter is NULL, and if so, throws the bad cast exception. The passed NULL is the value of std::basic_filebuf<...>::_M_codecvt.

    Why is this (private) member NULL? Interestingly, if I change all occurrences of "unsigned char" to just "char", it works. However, I'm reading binary data, which to mean should be stored as unsigned char. Is there any way I can make this work? Do I need to modify/specialize std::traits? Also, why is locale even playing an issue here?
    I see now that streambufs have a "pubimbue" and a "getloc" (getlocale and imbue locale) functions. Why? I thought streambufs handled reading/writing data to a stream, and that locale-dependant issues were the job of higher classes, such as istream/ostream/iostream?
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  2. #2
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902

    Red face

    Ok, it seems I might be able to answer some of my own questions now, after staring at the STL headers until my eyes crossed.

    There is a template class "codecvt" (Code [page?] coverter?) and the STL has two specializations for it included: char and wchar_t. The basic_streambuf class essentially wants one of:
    Code:
    std::codecvt<"character type", char, a "state" type>
    The first and third arguements depend on the template args to the streambuf. The middle one (in blue), however, is always char - I suspect this is what's coming from the file. So, a conversion from the bytestream of the file to usually either char or wchar_t.

    I thought it wouldn't be too hard to simply implement a codecvt subclass that took care of the conversion, however, this is where I'm wrong. It seems the two specializations provided by the STL are (and this is where I really hope I'm wrong) the only two possible. You can derive more codecvt's from the specialized ones, but not from the template itself. This is because the template includes several functions, such as:
    Code:
          virtual int
          do_max_length() const throw();
    There is no = 0 here, so it should be defined. It is defined for the two specializations, but not for the template. I've searched my entire compiler directory, and come up with nothing. All I get is linker errors on the functions like the one above, even though I define them in my class. Hopefully I'm really really really wrong here, but shouldn't there be implementations of those somewhere in my STL? Otherwise, my:
    Code:
    class ucvt
    	: public std::codecvt<unsigned char, char, mbstate_t>
    {
    public:
    	virtual ~ucvt() { }
    protected:
    
    	virtual bool do_always_noconv() { return true; }
    	virtual int do_max_length() { return 1; }
    };
    ... seems destined to fail.

    So, right now it seems my only option is to use a char array to represent binary data instead of an unsigned char array. I feel this is a bit wrong, but the STL isn't leaving me much wiggle room... I might be able to expose a public interface of an unsigned char array and cast like crazy to the streambufs... but ew. I'd rather not.
    Is basic_filebuf usable with unsigned char? Or only char (and why is char the datatype to represent a byte stream...) So confused...
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Bitmap scroll issues
    By Gerread in forum Windows Programming
    Replies: 4
    Last Post: 05-14-2007, 06:18 AM
  2. Solution to culling issues?
    By VirtualAce in forum Game Programming
    Replies: 4
    Last Post: 03-14-2006, 06:59 PM
  3. Directx issues
    By dpro in forum Game Programming
    Replies: 7
    Last Post: 03-30-2005, 01:58 PM
  4. gphoto2 issues
    By axon in forum Tech Board
    Replies: 3
    Last Post: 03-21-2004, 08:33 PM
  5. hexdump issues
    By daluu in forum C Programming
    Replies: 2
    Last Post: 03-04-2003, 09:01 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21