0

Using gcc 4.4.3 on Linux 2.6.32, I get bad_cast exceptions when connecting std::basic_ofstream to a FIFO.

Stepping though the debugger, I can see that the error is generated at various places in the standard library because the _M_codecvt member of the stream or filebuf object is NULL. Exactly where it happens depends on the order of operations, but it appears to be the same cause in each.

So am I doing something fundamentally stupid here? ofstream and ifstream work fine. Is there some reason that you shouldn't attach a stream of anything besides char to a FIFO?

Thanks in advance.

EDIT: Adding source code.

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <sys/stat.h>
#include <pthread.h>
using namespace std;

//#define CHAR char
#define CHAR unsigned char
bool still_writing = true;

void* reader (void*)
{
    basic_ifstream<CHAR> in ("FIFO", fstream::in);
    basic_streambuf<CHAR> *stream_buffer = in.rdbuf();

    bool no_reads = true;
    CHAR buffer[10];

    while (stream_buffer->in_avail() ||
           still_writing || 
           no_reads)
    {
        in.readsome(buffer, 10);
        const int got = (int)in.gcount();
        if (got > 0) {
            std::cerr << "Got something!\n";
            no_reads = false;
        }
    }
}

int main ()
{
    mkfifo ("FIFO", S_IRUSR | S_IWUSR);

    pthread_t reader_thread_id;
    pthread_create (&reader_thread_id, NULL, reader, NULL);

    basic_ofstream<CHAR> out ("FIFO");
    out << (CHAR) 70;
    still_writing = false;
    out.flush();

    pthread_join (reader_thread_id, NULL);

    remove ("FIFO");
}

In this version, the exception arises from stream_buffer->in_avail() If you swap the #define statements, everything is fine.

Mike B
  • 303
  • 4
  • 13
  • 1
    How exactly do you attach the stream? Do you have some example code? – sth Jun 10 '10 at 16:51
  • I've added test code. I'm just opening the FIFO with basic_(i/o)fstream. – Mike B Jun 10 '10 at 19:02
  • 1
    More a guess than a real answer: The stream tries to obtain an std::codecvt from the global locale, but fails to get one because the only standard codecvt's are for char and wchar_t. Workarounds: use char instead of unsigned char, or imbue the stream with a locale containing a codecvt of the right type. – Éric Malenfant Jun 10 '10 at 19:22
  • Thanks Éric. That seems likely, based on what I've been able to figure out. As interesting as it sounds to write a new facet, switching to char seems more prudent. – Mike B Jun 10 '10 at 20:22

1 Answers1

0

I had a similar issue. What I found out is that setting a skipws-flag must not be set. To ensure that use std::noskipws(your_stream_obj). I debugged it into the gcc-code and found out why that happened, but forgot it already.

Hope that helps...

ovanes
  • 5,483
  • 2
  • 34
  • 60