diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2012-08-03 09:32:05 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-08-23 02:55:17 +0200 |
commit | 6d56a216217045706121dc64ce9b3b25ec441b83 (patch) | |
tree | 65bd9528ef8fc5bb275d0f412c365c9b0188506f /src/corelib/global/qlogging.cpp | |
parent | a3e563c0913e5bc1607ea7f60187591ec7eabe50 (diff) |
Logging: make qEmergencyOut() not allocate from the heap
Commit 6e6b74c0 introduced heap allocation in the form of
QString::fromLatin1().utf16() into qEmergencyOut(), a function
that's called in OOM situations and in cases where another
exception is still in flight.
Luckily, QString::fromLatin1().utf16() is just a funny way of
copying an array of chars into an array of wchar_ts, so we do
that manually now and use a static wchar_t buffer. While at it,
also throw text elision into the mix.
This commit also fixes the message passed to _CrtDbgReportW().
What should be displayed is the emergency_buf, not the format
string.
Also remove a similar allocation in qt_message_output().
Change-Id: I2c44a298fc0927bb992de4977a7e4a7b47b16b26
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/global/qlogging.cpp')
-rw-r--r-- | src/corelib/global/qlogging.cpp | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 2446a99cde..653fe2ddc8 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -93,6 +93,22 @@ QT_BEGIN_NAMESPACE extern bool usingWinMain; #endif +#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) || defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) +static void convert_to_wchar_t_elided(wchar_t *d, size_t space, const char *s) Q_DECL_NOEXCEPT +{ + size_t len = qstrlen(s); + if (len + 1 > space) { + const size_t skip = len - space + 4; // 4 for "..." + '\0' + s += skip; + for (int i = 0; i < 3; ++i) + *d++ = L'.'; + } + while (*s) + *d++ = *s++; + *d++ = 0; +} +#endif + #if !defined(QT_NO_EXCEPTIONS) /*! \internal @@ -103,22 +119,26 @@ extern bool usingWinMain; static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap) Q_DECL_NOEXCEPT { char emergency_buf[256] = { '\0' }; - emergency_buf[255] = '\0'; + emergency_buf[sizeof emergency_buf - 1] = '\0'; +#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) || defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) + wchar_t emergency_bufL[sizeof emergency_buf]; +#endif + if (msg) - qvsnprintf(emergency_buf, 255, msg, ap); + qvsnprintf(emergency_buf, sizeof emergency_buf - 1, msg, ap); #if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) -#ifdef Q_OS_WINCE - OutputDebugStringW(reinterpret_cast<const wchar_t *> ( - QString::fromLatin1(emergency_buf).utf16())); -#else +# ifdef Q_OS_WINCE + convert_to_wchar_t_elided(emergency_bufL, sizeof emergency_buf, emergency_buf); + OutputDebugStringW(emergency_bufL); +# else if (usingWinMain) { OutputDebugStringA(emergency_buf); } else { fprintf(stderr, "%s", emergency_buf); fflush(stderr); } -#endif +# endif #else fprintf(stderr, "%s", emergency_buf); fflush(stderr); @@ -131,10 +151,12 @@ static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap) Q_DECL // get the current report mode int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); _CrtSetReportMode(_CRT_ERROR, reportMode); +# ifndef Q_OS_WINCE // otherwise already converted to wchar_t above + convert_to_wchar_t_elided(emergency_bufL, sizeof emergency_buf, emergency_buf); +# endif int ret = _CrtDbgReportW(_CRT_ERROR, _CRT_WIDE(__FILE__), __LINE__, _CRT_WIDE(QT_VERSION_STR), - reinterpret_cast<const wchar_t *> ( - QString::fromLatin1(msg).utf16())); + emergency_bufL); if (ret == 1) _CrtDbgBreak(); #endif @@ -729,12 +751,17 @@ void qt_message_output(QtMsgType msgType, const QMessageLogContext &context, con && qEnvironmentVariableIsSet("QT_FATAL_WARNINGS")) ) { #if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) + wchar_t contextFileL[256]; + // we probably should let the compiler do this for us, by + // declaring QMessageLogContext::file to be const wchar_t * in + // the first place, but the #ifdefery above is very complex + // and we wouldn't be able to change it later on... + convert_to_wchar_t_elided(contextFileL, sizeof contextFileL / sizeof *contextFileL, context.file); // get the current report mode int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); _CrtSetReportMode(_CRT_ERROR, reportMode); - int ret = _CrtDbgReportW(_CRT_ERROR, reinterpret_cast<const wchar_t *> ( - QString::fromLatin1(context.file).utf16()), + int ret = _CrtDbgReportW(_CRT_ERROR, contextFileL, context.line, _CRT_WIDE(QT_VERSION_STR), reinterpret_cast<const wchar_t *> ( message.utf16())); |