Error creating a std::string from a std::ostringstream
Error creating a std::string from a std::ostringstream
- Subject: Error creating a std::string from a std::ostringstream
- From: Scott Ribe <email@hidden>
- Date: Wed, 21 Nov 2007 17:01:09 -0700
- Thread-topic: Error creating a std::string from a std::ostringstream
I've been debugging a deadlock, and while doing that I've come across an odd
glitch in my logging. When the deadlock happens, the THROWMSG macro below
should log an error message and throw a string exception:
OSStatus err = MPWaitOnSemaphore( mSemId, kDurationMillisecond*1000*5 );
if( err )
THROWMSG( "error (", err, ") waiting for mp lock: ", mSemId );
This is a fatal failure. There is no intervening catch block to recover. The
top level function of the thread just has a catch handler that logs a
message and exits. But the above THROWMSG, instead of doing what I expect,
actually throws a basic_string::_S_create exception.
The mechanics of THROWMSG are pretty ugly. It uses macro magic to capture
function name, file name, and line information. It uses templates to combine
formatting strings and values in a type-safe way. And it uses __VA_ARGS__ in
combining the location args with the variable args list.
But here's the thing: that code works as expected in most cases. Putting the
following line of code at the beginning of main() logs the expected output
including the message "error (0) waiting for mp lock: 0x0" and then throws
that string:
THROWMSG( "error (", (OSStatus) 0, ") waiting for mp lock: ",
(MPSemaphoreId) 0 );
In fact, commenting out the if( err ) in the lock acquisition code from the
beginning of this message results in the first actual attempt at acquiring
one of these actual locks to log the expected message "error (0) waiting for
mp lock: 0x10000c" and throw.
The total string logged and thrown, including all the info about time &
thread & source, is ~270 characters. The process is running 250-500MB in
top, and other threads continue for hours with lots of memory allocation
going on, so it's not running out of memory. What is causing string creation
to fail?
I know the exception is coming out of that THROWMSG, because I log a message
just before the MPWaitOnSemaphore call, and 5 seconds + epsilon later the
catch of basic_string::_S_create is logged. (Also, there's a call to log a
successful lock acquisition, and it doesn't happen. And this happens in
pairs, always two threads. And looking at the log clearly shows me the
deadlock sequence. So, yep, I am *SURE* the mystery exception comes from
that exact line of code.)
BTW, I've found and fixed the deadlock--that's why I'm now free to obsess
over the logging ;-) I don't see this kind of error anywhere else in all the
logging I'm doing in this application, which is quite a lot.
The app runs on OS X Server 10.4.11 on a dual-processor G4, and was compiled
with Xcode 3.0.
OK, for those of you who might insist on seeing code... Here's the top-level
macro:
#define THROWMSG(...) do { LogMsg msg_( __VA_ARGS__ ); string str_(
msg_.str() ); \
LogErrorG( "Throwing: ", str_ ); throw (str_);
} while( 0 )
And some of LogMsg:
public:
const std::string str() const { return mStream.str(); }
template< class T1 >
LogMsg( const T1 & m1 )
{ mStream << m1; }
template< class T1, class T2 >
LogMsg( const T1 & m1, const T2 & m2 )
{ mStream << m1 << m2; }
...
protected:
std::ostringstream mStream;
And the LogErrorG macro expansion:
#define LogErrorG( ... ) do { LogMsgExpandG( Log::kLevelError, __VA_ARGS__
); } while (0)
#define LogMsgExpandG( lvl, ... ) \
do { LogMsg foo_( __VA_ARGS__ ); Log::GlobalLog()->LogMessage( lvl,
__func__, __FILE__, __LINE__, foo_ ); } while( 0 )
And the some of Log:
public:
static Log * GlobalLog();
enum LevelE { kLevelInfo = 0, kLevelWarning, kLevelError };
void LogMessage( LevelE lvl, const char * func, const char *
file, int linenum,
const LogMsg & msg );
And finally, yes, the LogMessage function is thread-safe ;-)
--
Scott Ribe
email@hidden
http://www.killerbytes.com/
(303) 722-0567 voice
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden