// http://foiani.com/cpp/boost/InterProcStringTest3.cpp // // Questions/comments to Anthony Foiani at // or // // This program seems to work when compiled without optimization: // // g++ -o InterProcStringTest3 InterProcStringTest3.cpp -lpthread -lrt // // ./InterProcStringTest3 // // **** no errors detected // // But I compile with -O2, it fails on Fedora 14 x86-64 (GCC 4.5.1, // Boost 1.44.0 stock but also with Boost 1.47.0): // // g++ -O2 -o InterProcStringTest3 InterProcStringTest3.cpp -lpthread -lrt // // ./InterProcStringTest3 // // InterProcStringTest3.cpp(150): test sv1 == sv3 failed in function: 'int test_main(int, char**)' // sv1="y\xffffffe2y", sv3="yyy" // InterProcStringTest3.cpp(162): test sv1 == sv5 failed in function: 'int test_main(int, char**)' // sv1="yyy\xffffffe2yy", sv5="yyyyyy" // **** 2 errors detected // // It works fine on Fedora 15 x86-64 (GCC 4.6.0, Boost 1.46.1): // // g++ -o InterProcStringTest3 InterProcStringTest3.cpp -lpthread -lrt // // ./InterProcStringTest3 // // **** no errors detected #include #include #include #include #include #include #include #include #include #include #include namespace // anonymous { // ===================================================================== // misc helpers std::string quoteChar( const char c ) { if ( c == '\0' ) return "\\0"; else if ( c == '\a' ) return "\\a"; else if ( c == '\b' ) return "\\b"; else if ( c == '\f' ) return "\\f"; else if ( c == '\n' ) return "\\n"; else if ( c == '\r' ) return "\\r"; else if ( c == '\t' ) return "\\t"; else if ( c == '\v' ) return "\\v"; else if ( c == '\\' ) return "\\\\"; else if ( c == '\'' ) return "\\'"; else if ( c == '\"' ) return "\\\""; else if ( ! std::isprint( c ) ) { static boost::format hex( "\\x%02x" ); hex % static_cast< unsigned int >( c ); return hex.str(); } else { char s[2] = " "; s[0] = c; return s; } } template < typename S > inline std::string quoteString( const S & s ) { std::string rv; rv.append( "\"" ); BOOST_FOREACH( const char & c, s ) rv.append( quoteChar( c ) ); rv.append( "\"" ); return rv; } // ===================================================================== // actual shared memory bits. // use a simple manager typedef boost::interprocess::managed_shared_memory ShmManagerType; // what type of character are we storing in our shared strings? typedef char ShmCharType; // we need an allocator for the string class to use; this // allocator is used to grab zero or more contiguous characters. typedef boost::interprocess::allocator< ShmCharType, ShmManagerType::segment_manager > ShmCharAllocatorType; // finally, we specify exactly what our shared strings are. typedef boost::interprocess::basic_string< ShmCharType, std::char_traits< ShmCharType >, ShmCharAllocatorType > ShmStringType; typedef std::string KeyType; typedef std::string ValueType; typedef ShmStringType StoredKeyType; typedef ShmStringType StoredValueType; inline KeyType toKey( const StoredKeyType & storedKey ) { return KeyType( storedKey.begin(), storedKey.end() ); } inline ValueType toValue( const StoredValueType & storedValue ) { return ValueType( storedValue.begin(), storedValue.end() ); } inline StoredKeyType toStoredKey( const KeyType & key, ShmManagerType & m_manager ) { return StoredKeyType( key.begin(), key.end(), m_manager.get_allocator< ShmCharType >() ); } inline StoredValueType toStoredValue( const ValueType & value, ShmManagerType & m_manager ) { return StoredValueType( value.begin(), value.end(), m_manager.get_allocator< ShmCharType >() ); } } // end namespace [anonymous] int test_main( int /* argc */, char * /* argv */ [] ) { const std::string & shmName( "ipstring" ); const std::size_t shmSize( 1024 * 1024 ); boost::interprocess::shared_memory_object::remove( shmName.c_str() ); ShmManagerType m_manager( boost::interprocess::open_or_create, shmName.c_str(), shmSize ); StoredValueType sv1( toStoredValue( "y", m_manager ) ); StoredValueType sv3( toStoredValue( "yyy", m_manager ) ); StoredValueType sv5( toStoredValue( "yyyyyy", m_manager ) ); sv1 = sv3; BOOST_CHECK( sv1 == sv3 ); if ( sv1 != sv3 ) std::clog << "sv1=" << quoteString( sv1 ) << ", " << "sv3=" << quoteString( sv3 ) << std::endl; sv1 = sv3; BOOST_CHECK( sv1 == sv3 ); if ( sv1 != sv3 ) std::clog << "sv1=" << quoteString( sv1 ) << ", " << "sv3=" << quoteString( sv3 ) << std::endl; sv1 = sv5; BOOST_CHECK( sv1 == sv5 ); if ( sv1 != sv5 ) std::clog << "sv1=" << quoteString( sv1 ) << ", " << "sv5=" << quoteString( sv5 ) << std::endl; sv1 = sv5; BOOST_CHECK( sv1 == sv5 ); if ( sv1 != sv5 ) std::clog << "sv1=" << quoteString( sv1 ) << ", " << "sv5=" << quoteString( sv5 ) << std::endl; return boost::exit_success; }