summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2012-08-03 09:32:05 +0200
committerQt by Nokia <qt-info@nokia.com>2012-08-23 02:55:17 +0200
commit6d56a216217045706121dc64ce9b3b25ec441b83 (patch)
tree65bd9528ef8fc5bb275d0f412c365c9b0188506f
parenta3e563c0913e5bc1607ea7f60187591ec7eabe50 (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>
-rw-r--r--src/corelib/global/qlogging.cpp49
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()));