boost::iostreams: only with std::cout?

Hi, I would love to use the boost::iostreams lib, so I created a filter (which, in this case, does encryption) but instead of passing it std::cout I would like to pass it some other stream, a stringstream for instance (or any kind of ostream/istream, depending on the direction). However, I was very surprised to find the following code taking 100% cpu and not returning. It probably means I did something wrong, but I can't seem to find it. void test_encryption_filter() { const char* speech = "They sorely misunderestimate the American people if they " "think we will let them obtain nucular weapons. This " "malfeance will not stand."; // std::ostream which writes to standard output, filtered by a // encryption_output_filter. boost::io::filtering_ostream out; out.push(encryption::code_book::output_filter()); //out.push(std:cout); //this works std::ostringstream os; out.push(os); //this does not // Print unfiltered code. std::cout << "**** Speech unfiltered ****\n" << speech << "\n\n"; // Print filtered code: std::cout << "**** Speech with encryption filter ****\n"; out << speech << "\n\n"; } (testing puspose) filter looks like (namespace omitted): struct output_filter : public multichar_output_filter { template<typename Sink> void write(Sink& snk, const char* s, streamsize n) { while (n-- > 0) boost::io::put(snk, toupper(*s++)); } }; With std::cout this works fine, with std::ostringstream it does not. So could anyone please tell me what I am missing? Thanks in advance, Dirk ********************************************************************** This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you are not the intended recipient, any disclosure, copying, use, or distribution of the information included in this message and any attachments is prohibited. If you have received this email in error please notify our system management at postmaster@optiver.com and immediately and permanently delete this message and any attachments. ********************************************

Dirk Griffioen wrote:
Hi,
I would love to use the boost::iostreams lib,
Great!
so I created a filter (which, in this case, does encryption)
but instead of passing it std::cout I would like to pass it some other stream, a stringstream for instance (or any kind of ostream/istream, depending on the direction).
Right, you're supposed to be able to do this.
However, I was very surprised to find the following code taking 100% cpu and not returning. It probably means I did something wrong, but I can't seem to find it.
I've changed you're code a bit (see attached), since the code you posted doesn't compile. Here's the situation: - The code works with GCC 3.4 (Cygwin), Intel 8.0 with Dinkumware, and VC7.1. - If the line out << speech << std::endl; is replaced by out << speech << "\n"; the code works with GCC 3.4, Intel 8.0 and VC7.1 in release mode, but hangs at the end of the function test_encryption_filter() with VC7.1 in debug mode. (Note when I say "works", it might not work as you expected, since the stream is never flushed so the output is empty.) I'm not sure why the program hangs in debug mode, but I'm hoping it will be easier to track down than if it only failed in release mode ;-) It may be a problem in how resources are cleaned up when a stream is closed, which has proved to be the main source of bugs. I'm not sure when I'll be able to work on it, but I'll let you know what I discover. Jonathan begin 666 example.cpp M(VEN8VQU9&4@/&EO<W1R96%M/@T*(VEN8VQU9&4@/'-S=')E86T^#0HC:6YC M;'5D92 \8F]O<W0O:6]S=')E86US+V-O;F-E<'1S+FAP<#X-"B-I;F-L=61E M(#QB;V]S="]I;W-T<F5A;7,O9FEL=&5R:6YG7W-T<F5A;2YH<' ^#0H-"G5S M:6YG(&YA;65S<&%C92!S=&0[#0IU<VEN9R!N86UE<W!A8V4@8F]O<W0Z.FEO M<W1R96%M<SL-"@T*<W1R=6-T('1E<W1?;W5T<'5T7V9I;'1E<B Z('!U8FQI M8R!M=6QT:6-H87)?;W5T<'5T7V9I;'1E<B![#0H@(" @=&5M<&QA=&4\='EP M96YA;64@4VEN:SX-"B @("!V;VED('=R:71E*%-I;FLF('-N:RP@8V]N<W0@ M8VAA<BH@<RP@<W1R96%M<VEZ92!N*0T*(" @(" @("![#0H@(" @(" @(" @ M("!W:&EL92 H;BTM(#X@,"D-"B @(" @(" @(" @(" @("!B;V]S=#HZ:6]S M=')E86US.CIP=70H<VYK+"!T;W5P<&5R*"IS*RLI*3L-"B @(" @(" @?0T* M?3L-"@T*=F]I9"!T97-T7V5N8W)Y<'1I;VY?9FEL=&5R*"D-"@T*('L-"@T* M(" @(&-O;G-T(&-H87(J('-P965C:" ]#0H-"B @(" @(" @(E1H97D@<V]R M96QY(&UI<W5N9&5R97-T:6UA=&4@=&AE($%M97)I8V%N('!E;W!L92!I9B!T M:&5Y("(-"@T*(" @(" @(" B=&AI;FL@=V4@=VEL;"!L970@=&AE;2!O8G1A M:6X@;G5C=6QA<B!W96%P;VYS+B!4:&ES("(-"@T*(" @(" @(" B;6%L9F5A M;F-E('=I;&P@;F]T('-T86YD+B([#0H-"@T*(" @("\O('-T9#HZ;W-T<F5A M;2!W:&EC:"!W<FET97,@=&\@82!S=')I;F=S=')E86T@+"!F:6QT97)E9"!B M>2!A#0H@(" @+R\@=&5S=%]O=71P=71?9FEL=&5R+@T*#0H@(" @8F]O<W0Z M.FEO<W1R96%M<SHZ9FEL=&5R:6YG7V]S=')E86T@;W5T.PT*#0H@(" @;W5T M+G!U<V@H=&5S=%]O=71P=71?9FEL=&5R*"DI.PT*#0H@(" @<W1D.CIO<W1R M:6YG<W1R96%M(&]S.PT*#0H@(" @;W5T+G!U<V@H;W,I.PT*#0H@(" @+R\@ M5W)I=&4@9FEL=&5R960@8V]D92!T;R!S=')I;F=S=')E86TZ#0H-"B @("!O M=70@/#P@<W!E96-H(#P\(")<;B([#0H-"B @(" O+R!7<FET92!S=')I;F=S M=')E86T@8V]N=&5N=',@=&\@8V]U=#H-"B @(" -"B @("!S=&0Z.F-O=70@ M/#P@;W,N<W1R*"D[#0I]#0H-"FEN="!M86EN*"D-"GL-"B @("!T97-T7V5N 78W)Y<'1I;VY?9FEL=&5R*"D[#0I]#0H` ` end

Dirk Griffioen wrote:
I would love to use the boost::iostreams lib, so I created a filter (which, in this case, does encryption)
but instead of passing it std::cout I would like to pass it some other stream, a stringstream for instance (or any kind of ostream/istream, depending on the direction).
However, I was very surprised to find the following code taking 100% cpu and not returning. It probably means I did something wrong, but I can't seem to find it.
Here's a cleaned up example that reproduces the bug (when endl is replaces by "\n"). It seems the filter is a red herring. Jonathan #include <iostream> #include <sstream> #include <boost/iostreams/filtering_stream.hpp> int main() { boost::iostreams::filtering_ostream out; std::ostringstream os; out.push(os); out << "test" << std::endl; //out << "test" << "\n"; std::cout << os.str(); }

Dirk Griffioen wrote:
Hi,
I would love to use the boost::iostreams lib, so I created a filter (which, in this case, does encryption)
but instead of passing it std::cout I would like to pass it some other stream, a stringstream for instance (or any kind of ostream/istream, depending on the direction).
However, I was very surprised to find the following code taking 100% cpu and not returning. It probably means I did something wrong, but I can't seem to find it.
I found the problem, and fortunately it is not an iostreams bug. But the fact that the source of trouble was not obvious to me makes it clear that many others will run into the same problem, so it needs to be stressed somewhere in the documentation, maybe in several places. The problem is that the stringstream is being freed while it is still owned by the filtering_stream, which attempts to flush the stringstream in its destructor. Most filters and devices are stored as copies, or are reference-counted, so usually there is no problem. streams and stream buffers are stored by reference, however, and so must outlive the containing filtering_stream. (More precisely, a stream or stream buffer must outlive the filtering_stream or be removed from the filtering_stream's internal chain before it is destroyed.) Jonathan Turkanis wrote:
#include <iostream> #include <sstream> #include <boost/iostreams/filtering_stream.hpp>
int main() { boost::iostreams::filtering_ostream out; std::ostringstream os;
Note: os is destroyed before out!!!
out.push(os); out << "test" << std::endl; //out << "test" << "\n"; std::cout << os.str(); }
If the first two declarations are interchanged, everything is peachy. The reason it worked with cout is that cout is guaranteed to be available until the end of the program. Jonathan
participants (2)
-
Dirk Griffioen
-
Jonathan Turkanis