summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorRobert Griebl <rgriebl@trolltech.com>2009-06-10 11:46:23 (GMT)
committerRobert Griebl <rgriebl@trolltech.com>2009-06-10 11:46:23 (GMT)
commit7604f8087f88171ef933d8ae08f501467e647338 (patch)
tree51d071f462ed48d0b25884d9f62b8ba11c5dff13 /src/corelib
parent8c265860b41214daade7c8a28237c1e07ea71a3c (diff)
downloadQt-7604f8087f88171ef933d8ae08f501467e647338.zip
Qt-7604f8087f88171ef933d8ae08f501467e647338.tar.gz
Qt-7604f8087f88171ef933d8ae08f501467e647338.tar.bz2
Make Qt exception safer.
Squashed commit of the branch haralds-haralds-qt-s60-topics/topic/exceptions, which also contains the full history. Rev-By: Harald Fernengel Rev-By: Ralf Engels
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/codecs/qisciicodec.cpp1
-rw-r--r--src/corelib/codecs/qtextcodec.cpp21
-rw-r--r--src/corelib/concurrent/qthreadpool.cpp6
-rw-r--r--src/corelib/global/qglobal.cpp143
-rw-r--r--src/corelib/global/qglobal.h97
-rw-r--r--src/corelib/global/qlibraryinfo.cpp28
-rw-r--r--src/corelib/io/qabstractfileengine.cpp3
-rw-r--r--src/corelib/io/qabstractfileengine.h4
-rw-r--r--src/corelib/io/qdebug.h7
-rw-r--r--src/corelib/io/qdir.cpp3
-rw-r--r--src/corelib/io/qdir.h3
-rw-r--r--src/corelib/io/qfile.cpp5
-rw-r--r--src/corelib/io/qfileinfo.cpp2
-rw-r--r--src/corelib/io/qfileinfo.h3
-rw-r--r--src/corelib/io/qfilesystemwatcher_symbian.cpp8
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp24
-rw-r--r--src/corelib/io/qiodevice.h3
-rw-r--r--src/corelib/io/qprocess_symbian.cpp1
-rw-r--r--src/corelib/io/qresource.cpp1
-rw-r--r--src/corelib/io/qresource.h2
-rw-r--r--src/corelib/io/qsettings.cpp68
-rw-r--r--src/corelib/io/qsettings.h2
-rw-r--r--src/corelib/io/qsettings_p.h2
-rw-r--r--src/corelib/io/qtextstream.cpp3
-rw-r--r--src/corelib/io/qtextstream.h3
-rw-r--r--src/corelib/kernel/qcore_symbian_p.cpp19
-rw-r--r--src/corelib/kernel/qcore_symbian_p.h4
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp91
-rw-r--r--src/corelib/kernel/qcoreapplication.h2
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian.cpp195
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian_p.h3
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp21
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h1
-rw-r--r--src/corelib/kernel/qobject.cpp44
-rw-r--r--src/corelib/kernel/qobject.h3
-rw-r--r--src/corelib/kernel/qsharedmemory_symbian.cpp14
-rw-r--r--src/corelib/kernel/qsystemsemaphore.cpp3
-rw-r--r--src/corelib/kernel/qsystemsemaphore.h3
-rw-r--r--src/corelib/kernel/qsystemsemaphore_symbian.cpp7
-rw-r--r--src/corelib/plugin/qlibrary.cpp7
-rw-r--r--src/corelib/thread/qthread.cpp15
-rw-r--r--src/corelib/thread/qthread_unix.cpp9
-rw-r--r--src/corelib/thread/qthread_win.cpp9
-rw-r--r--src/corelib/thread/qthreadstorage.cpp14
-rw-r--r--src/corelib/tools/qbitarray.cpp2
-rw-r--r--src/corelib/tools/qbytearray.cpp55
-rw-r--r--src/corelib/tools/qdatetime.cpp14
-rw-r--r--src/corelib/tools/qdatetime.h3
-rw-r--r--src/corelib/tools/qharfbuzz.cpp1
-rw-r--r--src/corelib/tools/qhash.cpp78
-rw-r--r--src/corelib/tools/qhash.h39
-rw-r--r--src/corelib/tools/qlinkedlist.h44
-rw-r--r--src/corelib/tools/qlist.h101
-rw-r--r--src/corelib/tools/qlistdata.cpp22
-rw-r--r--src/corelib/tools/qlocale.cpp3
-rw-r--r--src/corelib/tools/qmap.cpp35
-rw-r--r--src/corelib/tools/qmap.h35
-rw-r--r--src/corelib/tools/qpodlist_p.h192
-rw-r--r--src/corelib/tools/qregexp.cpp25
-rw-r--r--src/corelib/tools/qringbuffer_p.h5
-rw-r--r--src/corelib/tools/qscopedpointer.cpp132
-rw-r--r--src/corelib/tools/qscopedpointer.h199
-rw-r--r--src/corelib/tools/qshareddata.cpp2
-rw-r--r--src/corelib/tools/qsharedpointer.cpp9
-rw-r--r--src/corelib/tools/qstring.cpp138
-rw-r--r--src/corelib/tools/qtextboundaryfinder.cpp10
-rw-r--r--src/corelib/tools/qvarlengtharray.h80
-rw-r--r--src/corelib/tools/qvector.cpp1
-rw-r--r--src/corelib/tools/qvector.h98
-rw-r--r--src/corelib/tools/tools.pri3
-rw-r--r--src/corelib/xml/qxmlstream.cpp5
-rw-r--r--src/corelib/xml/qxmlstream.h5
72 files changed, 1450 insertions, 793 deletions
diff --git a/src/corelib/codecs/qisciicodec.cpp b/src/corelib/codecs/qisciicodec.cpp
index dd2bc8d..5619580 100644
--- a/src/corelib/codecs/qisciicodec.cpp
+++ b/src/corelib/codecs/qisciicodec.cpp
@@ -38,7 +38,6 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-
#include "qisciicodec_p.h"
#include "qlist.h"
diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp
index 6e8ffa1..cfb62c7 100644
--- a/src/corelib/codecs/qtextcodec.cpp
+++ b/src/corelib/codecs/qtextcodec.cpp
@@ -92,6 +92,11 @@
# define QT_NO_SETLOCALE
#endif
+#if 0 // ### TODO - remove me!
+// enabling this is not exception safe!
+#define Q_DEBUG_TEXTCODEC
+#endif
+
QT_BEGIN_NAMESPACE
#ifndef QT_NO_TEXTCODECPLUGIN
@@ -165,7 +170,9 @@ static QTextCodec *createForMib(int mib)
}
static QList<QTextCodec*> *all = 0;
+#ifdef Q_DEBUG_TEXTCODEC
static bool destroying_is_ok = false;
+#endif
static QTextCodec *localeMapper = 0;
QTextCodec *QTextCodec::cftr = 0;
@@ -187,15 +194,21 @@ QTextCodecCleanup::~QTextCodecCleanup()
if (!all)
return;
+#ifdef Q_DEBUG_TEXTCODEC
destroying_is_ok = true;
+#endif
- while (all->size())
- delete all->takeFirst();
+ for (QList<QTextCodec *>::const_iterator it = all->constBegin()
+ ; it != all->constEnd(); ++it) {
+ delete *it;
+ }
delete all;
all = 0;
localeMapper = 0;
+#ifdef Q_DEBUG_TEXTCODEC
destroying_is_ok = false;
+#endif
}
Q_GLOBAL_STATIC(QTextCodecCleanup, createQTextCodecCleanup)
@@ -659,8 +672,10 @@ static void setup()
if (all)
return;
+#ifdef Q_DEBUG_TEXTCODEC
if (destroying_is_ok)
qWarning("QTextCodec: Creating new codec during codec cleanup");
+#endif
all = new QList<QTextCodec*>;
// create the cleanup object to cleanup all codecs on exit
(void) createQTextCodecCleanup();
@@ -915,8 +930,10 @@ QTextCodec::QTextCodec()
*/
QTextCodec::~QTextCodec()
{
+#ifdef Q_DEBUG_TEXTCODEC
if (!destroying_is_ok)
qWarning("QTextCodec::~QTextCodec: Called by application");
+#endif
if (all)
all->removeAll(this);
}
diff --git a/src/corelib/concurrent/qthreadpool.cpp b/src/corelib/concurrent/qthreadpool.cpp
index 30edfd4..8913b56 100644
--- a/src/corelib/concurrent/qthreadpool.cpp
+++ b/src/corelib/concurrent/qthreadpool.cpp
@@ -246,14 +246,14 @@ bool QThreadPoolPrivate::tooManyThreadsActive() const
*/
void QThreadPoolPrivate::startThread(QRunnable *runnable)
{
- QThreadPoolThread *thread = new QThreadPoolThread(this);
- allThreads.insert(thread);
+ QScopedPointer <QThreadPoolThread> thread(new QThreadPoolThread(this));
+ allThreads.insert(thread.data());
++activeThreads;
if (runnable->autoDelete())
++runnable->ref;
thread->runnable = runnable;
- thread->start();
+ thread.take()->start();
}
/*! \internal
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index ca243e7..484c618 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -1929,6 +1929,15 @@ void qt_check_pointer(const char *n, int l)
qWarning("In file %s, line %d: Out of memory", n, l);
}
+/* \internal
+ Allows you to throw an exception without including <new>
+ Called internally from Q_CHECK_PTR on certain OS combinations
+*/
+void qBadAlloc()
+{
+ QT_THROW(std::bad_alloc());
+}
+
/*
The Q_ASSERT macro calls this function when the test fails.
*/
@@ -2177,7 +2186,11 @@ void qt_message_output(QtMsgType msgType, const char *buf)
#if defined(Q_OS_SYMBIAN)
__DEBUGGER(); // on the emulator, get the debugger to kick in if there's one around
- User::Invariant(); // Panic the current thread
+ TBuf<256> tmp;
+ TPtrC8 ptr(reinterpret_cast<const TUint8*>(buf));
+ TInt len = Min(tmp.MaxLength(), ptr.Length());
+ tmp.Copy(ptr.Left(len));
+ User::Panic(tmp, 0); // Panic the current thread
#elif (defined(Q_OS_UNIX) || defined(Q_CC_MINGW))
abort(); // trap; generates core dump
#else
@@ -2186,6 +2199,48 @@ void qt_message_output(QtMsgType msgType, const char *buf)
}
}
+#if !defined(QT_NO_EXCEPTIONS)
+/*!
+ \internal
+ Uses a local buffer to output the message. Not locale safe + cuts off
+ everything after character 1023, but will work in out of memory situations.
+*/
+static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap)
+{
+ char emergency_buf[1024] = { '\0' };
+ emergency_buf[1023] = '\0';
+ if (msg)
+ qvsnprintf(emergency_buf, 1023, msg, ap);
+ qt_message_output(msgType, emergency_buf);
+}
+#endif
+
+/*!
+ \internal
+*/
+static void qt_message(QtMsgType msgType, const char *msg, va_list ap)
+{
+#if !defined(QT_NO_EXCEPTIONS)
+ if (std::uncaught_exception()) {
+ qEmergencyOut(msgType, msg, ap);
+ return;
+ }
+#endif
+ QByteArray buf;
+ if (msg) {
+ QT_TRY {
+ buf = QString().vsprintf(msg, ap).toLocal8Bit();
+ } QT_CATCH(const std::bad_alloc &) {
+#if !defined(QT_NO_EXCEPTIONS)
+ qEmergencyOut(msgType, msg, ap);
+ // don't rethrow - we use qWarning and friends in destructors.
+ return;
+#endif
+ }
+ }
+ qt_message_output(msgType, buf.constData());
+}
+
#undef qDebug
/*!
\relates <QtGlobal>
@@ -2223,14 +2278,10 @@ void qt_message_output(QtMsgType msgType, const char *buf)
*/
void qDebug(const char *msg, ...)
{
- QString buf;
va_list ap;
- va_start(ap, msg); // use variable arg list
- if (msg)
- buf.vsprintf(msg, ap);
+ va_start(ap, msg); // use variable arg list
+ qt_message(QtDebugMsg, msg, ap);
va_end(ap);
-
- qt_message_output(QtDebugMsg, buf.toLocal8Bit().constData());
}
#undef qWarning
@@ -2267,14 +2318,10 @@ void qDebug(const char *msg, ...)
*/
void qWarning(const char *msg, ...)
{
- QString buf;
va_list ap;
va_start(ap, msg); // use variable arg list
- if (msg)
- buf.vsprintf(msg, ap);
+ qt_message(QtWarningMsg, msg, ap);
va_end(ap);
-
- qt_message_output(QtWarningMsg, buf.toLocal8Bit().constData());
}
/*!
@@ -2307,15 +2354,12 @@ void qWarning(const char *msg, ...)
*/
void qCritical(const char *msg, ...)
{
- QString buf;
va_list ap;
va_start(ap, msg); // use variable arg list
- if (msg)
- buf.vsprintf(msg, ap);
+ qt_message(QtCriticalMsg, msg, ap);
va_end(ap);
-
- qt_message_output(QtCriticalMsg, buf.toLocal8Bit().constData());
}
+
#ifdef QT3_SUPPORT
void qSystemWarning(const char *msg, int code)
{ qCritical("%s (%s)", msg, qt_error_string(code).toLocal8Bit().constData()); }
@@ -2323,6 +2367,8 @@ void qSystemWarning(const char *msg, int code)
void qErrnoWarning(const char *msg, ...)
{
+ // qt_error_string() will allocate anyway, so we don't have
+ // to be careful here (like we do in plain qWarning())
QString buf;
va_list ap;
va_start(ap, msg);
@@ -2335,6 +2381,8 @@ void qErrnoWarning(const char *msg, ...)
void qErrnoWarning(int code, const char *msg, ...)
{
+ // qt_error_string() will allocate anyway, so we don't have
+ // to be careful here (like we do in plain qWarning())
QString buf;
va_list ap;
va_start(ap, msg);
@@ -2371,14 +2419,10 @@ void qErrnoWarning(int code, const char *msg, ...)
*/
void qFatal(const char *msg, ...)
{
- QString buf;
va_list ap;
va_start(ap, msg); // use variable arg list
- if (msg)
- buf.vsprintf(msg, ap);
+ qt_message(QtFatalMsg, msg, ap);
va_end(ap);
-
- qt_message_output(QtFatalMsg, buf.toLocal8Bit().constData());
}
// getenv is declared as deprecated in VS2005. This function
@@ -3166,4 +3210,59 @@ bool QInternal::callFunction(InternalFunction func, void **args)
\sa Q_DECL_EXPORT
*/
+#if defined(Q_OS_SYMBIAN)
+
+#include <typeinfo>
+
+const char* QSymbianLeaveException::what() const throw()
+{
+ static const char str[] = "Symbian leave exception %d";
+ static char msg[sizeof(str)+12];
+ sprintf(msg, str, error);
+ return msg;
+}
+
+void qt_translateSymbianErrorToException(int error)
+{
+ if (error >= KErrNone)
+ return; // do nothing - not an exception
+ switch (error) {
+ case KErrNoMemory:
+ throw std::bad_alloc();
+ default:
+ throw QSymbianLeaveException(error);
+ }
+}
+
+void qt_translateExceptionToSymbianErrorL(const std::exception& aThrow)
+{
+ User::Leave(qt_translateExceptionToSymbianError(aThrow));
+}
+
+int qt_translateExceptionToSymbianError(const std::exception& aThrow)
+{
+ const std::type_info& atype = typeid(aThrow);
+ int err = KErrGeneral;
+
+ if(atype == typeid (std::bad_alloc))
+ err = KErrNoMemory;
+ else if(atype == typeid(QSymbianLeaveException))
+ err = static_cast<const QSymbianLeaveException&>(aThrow).error;
+ else if(atype == typeid(std::invalid_argument))
+ err = KErrArgument;
+ else if(atype == typeid(std::out_of_range))
+ // std::out_of_range is of type logic_error which by definition means that it is
+ // "presumably detectable before the program executes".
+ // std::out_of_range is used to report an argument is not within the expected range.
+ // The description of KErrArgument says an argument is out of range. Hence the mapping.
+ err = KErrArgument;
+ else if(atype == typeid(std::overflow_error))
+ err = KErrOverflow;
+ else if(atype == typeid(std::underflow_error))
+ err = KErrUnderflow;
+
+ return err;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index b075db6..030840e 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -1301,6 +1301,32 @@ class QDataStream;
# define Q_AUTOTEST_EXPORT
#endif
+inline void qt_noop() {}
+
+/* These wrap try/catch so we can switch off exceptions later.
+
+ Beware - do not use more than one QT_CATCH per QT_TRY, and do not use
+ the exception instance in the catch block.
+ If you can't live with those constraints, don't use these macros.
+ Use the QT_NO_EXCEPTIONS macro to protect your code instead.
+*/
+
+#ifdef QT_BOOTSTRAPPED
+# define QT_NO_EXCEPTIONS
+#endif
+
+#ifdef QT_NO_EXCEPTIONS
+# define QT_TRY if (true)
+# define QT_CATCH(A) else
+# define QT_THROW(A) qt_noop()
+# define QT_RETHROW qt_noop()
+#else
+# define QT_TRY try
+# define QT_CATCH(A) catch (A)
+# define QT_THROW(A) throw A
+# define QT_RETHROW throw
+#endif
+
/*
System information
*/
@@ -1554,8 +1580,6 @@ inline QNoDebug qDebug();
#endif
-inline void qt_noop() {}
-
Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line);
#if !defined(Q_ASSERT)
@@ -1581,11 +1605,16 @@ Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *
#endif
Q_CORE_EXPORT void qt_check_pointer(const char *, int);
+Q_CORE_EXPORT void qBadAlloc();
-#ifndef QT_NO_DEBUG
-# define Q_CHECK_PTR(p) do {if(!(p))qt_check_pointer(__FILE__,__LINE__);} while (0)
+#ifdef QT_NO_EXCEPTIONS
+# if defined(QT_NO_DEBUG)
+# define Q_CHECK_PTR(p) qt_noop();
+# else
+# define Q_CHECK_PTR(p) do {if(!(p))qt_check_pointer(__FILE__,__LINE__);} while (0)
+# endif
#else
-# define Q_CHECK_PTR(p)
+# define Q_CHECK_PTR(p) do { if (!(p)) qBadAlloc(); } while (0)
#endif
#if (defined(Q_CC_GNU) && !defined(Q_OS_SOLARIS)) || defined(Q_CC_HPACC)
@@ -1734,12 +1763,12 @@ public:
static TYPE *NAME() \
{ \
if (!this_##NAME.pointer && !this_##NAME.destroyed) { \
- TYPE *x = new TYPE; \
+ QScopedPointer<TYPE > x(new TYPE); \
INITIALIZER; \
- if (!this_##NAME.pointer.testAndSetOrdered(0, x)) \
- delete x; \
- else \
+ if (this_##NAME.pointer.testAndSetOrdered(0, x.data())) { \
static QGlobalStaticDeleter<TYPE > cleanup(this_##NAME); \
+ x.take(); \
+ } \
} \
return this_##NAME.pointer; \
}
@@ -2193,8 +2222,8 @@ inline const QForeachContainer<T> *qForeachContainer(const QForeachContainerBase
#endif
#define Q_DECLARE_PRIVATE(Class) \
- inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(d_ptr); } \
- inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(d_ptr); } \
+ inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(d_ptr.data()); } \
+ inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(d_ptr.data()); } \
friend class Class##Private;
#define Q_DECLARE_PRIVATE_D(Dptr, Class) \
@@ -2242,7 +2271,9 @@ inline const QForeachContainer<T> *qForeachContainer(const QForeachContainerBase
Class(const Class &); \
Class &operator=(const Class &);
#else
-# define Q_DISABLE_COPY(Class)
+# define Q_DISABLE_COPY(Class) \
+ Class(const Class &); \
+ Class &operator=(const Class &);
#endif
class QByteArray;
@@ -2434,6 +2465,48 @@ QT_LICENSED_MODULE(DBus)
# define QT_NO_CONCURRENT_FILTER
#endif
+#if defined(Q_OS_SYMBIAN)
+
+#include <stdexcept>
+class QSymbianLeaveException : public std::exception
+{
+public:
+ QSymbianLeaveException(int err) : error(err){ }
+ const char* what() const throw();
+public:
+ int error;
+};
+
+Q_CORE_EXPORT void qt_translateSymbianErrorToException(int error);
+Q_CORE_EXPORT void qt_translateExceptionToSymbianErrorL(const std::exception& ex);
+Q_CORE_EXPORT int qt_translateExceptionToSymbianError(const std::exception& ex);
+
+#define QT_TRANSLATE_SYMBIAN_LEAVE_TO_EXCEPTION(f) \
+ { \
+ TInt error; \
+ TRAP(error, f); \
+ if (error) \
+ qt_translateSymbianErrorToException(error); \
+ }
+
+#define QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_ERROR(err, f) \
+ { \
+ err = KErrNone; \
+ try { \
+ f; \
+ } catch (const std::exception &ex) { \
+ err = qt_translateExceptionToSymbianError(ex); \
+ } \
+ }
+
+#define QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_LEAVE(f) \
+ { \
+ TInt err; \
+ QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_ERROR(err, f) \
+ User::LeaveIfError(err); \
+ }
+#endif
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index 29e356e..5e4b9bd 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -40,11 +40,11 @@
****************************************************************************/
#include "qdir.h"
-#include "qfile.h"
+#include "qfile.h"
#include "qconfig.h"
#include "qsettings.h"
#include "qlibraryinfo.h"
-#include "qpointer.h"
+#include "qscopedpointer.h"
#ifdef QT_BUILD_QMAKE
QT_BEGIN_NAMESPACE
@@ -67,8 +67,7 @@ QT_BEGIN_NAMESPACE
struct QLibrarySettings
{
QLibrarySettings();
- ~QLibrarySettings() { delete static_cast<QSettings *>(settings); }
- QSettings *settings;
+ QScopedPointer<QSettings> settings;
};
Q_GLOBAL_STATIC(QLibrarySettings, qt_library_settings)
@@ -79,32 +78,19 @@ public:
static void cleanup()
{
QLibrarySettings *ls = qt_library_settings();
- if (ls) {
- delete static_cast<QSettings *>(ls->settings);
- ls->settings = 0;
- }
+ if (ls)
+ ls->settings.reset(0);
}
static QSettings *configuration()
{
-#ifdef QT_NO_THREAD
- // This recursion guard should be a temporary solution; the recursive
- // dependency should be found and removed.
- static bool initializing = false;
- if (initializing)
- return 0;
- initializing = true;
-#endif
QLibrarySettings *ls = qt_library_settings();
-#ifdef QT_NO_THREAD
- initializing = false;
-#endif
- return ls ? static_cast<QSettings *>(qt_library_settings()->settings) : (QSettings*)0;
+ return ls ? ls->settings.data() : 0;
}
};
QLibrarySettings::QLibrarySettings()
+ : settings(QLibraryInfoPrivate::findConfiguration())
{
- settings = QLibraryInfoPrivate::findConfiguration();
#ifndef QT_BUILD_QMAKE
qAddPostRoutine(QLibraryInfoPrivate::cleanup);
#endif
diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp
index bedc121..63d4944 100644
--- a/src/corelib/io/qabstractfileengine.cpp
+++ b/src/corelib/io/qabstractfileengine.cpp
@@ -352,8 +352,6 @@ QAbstractFileEngine::QAbstractFileEngine(QAbstractFileEnginePrivate &dd) : d_ptr
*/
QAbstractFileEngine::~QAbstractFileEngine()
{
- delete d_ptr;
- d_ptr = 0;
}
/*!
@@ -881,7 +879,6 @@ QAbstractFileEngineIterator::QAbstractFileEngineIterator(QDir::Filters filters,
*/
QAbstractFileEngineIterator::~QAbstractFileEngineIterator()
{
- delete d;
}
/*!
diff --git a/src/corelib/io/qabstractfileengine.h b/src/corelib/io/qabstractfileengine.h
index d742467..5b75343 100644
--- a/src/corelib/io/qabstractfileengine.h
+++ b/src/corelib/io/qabstractfileengine.h
@@ -193,7 +193,7 @@ protected:
QAbstractFileEngine();
QAbstractFileEngine(QAbstractFileEnginePrivate &);
- QAbstractFileEnginePrivate *d_ptr;
+ QScopedPointer<QAbstractFileEnginePrivate> d_ptr;
private:
Q_DECLARE_PRIVATE(QAbstractFileEngine)
Q_DISABLE_COPY(QAbstractFileEngine)
@@ -237,7 +237,7 @@ private:
friend class QDirIterator;
friend class QDirIteratorPrivate;
void setPath(const QString &path);
- QAbstractFileEngineIteratorPrivate *d;
+ QScopedPointer<QAbstractFileEngineIteratorPrivate> d;
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index 8334146..60dc688 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -79,8 +79,11 @@ public:
inline QDebug &operator=(const QDebug &other);
inline ~QDebug() {
if (!--stream->ref) {
- if(stream->message_output)
- qt_message_output(stream->type, stream->buffer.toLocal8Bit().data());
+ if(stream->message_output) {
+ QT_TRY {
+ qt_message_output(stream->type, stream->buffer.toLocal8Bit().data());
+ } QT_CATCH(std::bad_alloc) { /* We're out of memory - give up. */ }
+ }
delete stream;
}
}
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 901641c..e1cc7ac 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -83,6 +83,7 @@ class QDirPrivate
QDir *q_ptr;
Q_DECLARE_PUBLIC(QDir)
+ friend class QScopedPointer<QDirPrivate>;
protected:
QDirPrivate(QDir*, const QDir *copy=0);
~QDirPrivate();
@@ -573,8 +574,6 @@ QDir::QDir(const QDir &dir) : d_ptr(new QDirPrivate(this, &dir))
QDir::~QDir()
{
- delete d_ptr;
- d_ptr = 0;
}
/*!
diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h
index c4f6b1a..ac80094 100644
--- a/src/corelib/io/qdir.h
+++ b/src/corelib/io/qdir.h
@@ -45,6 +45,7 @@
#include <QtCore/qstring.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qstringlist.h>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_HEADER
@@ -57,7 +58,7 @@ class QDirPrivate;
class Q_CORE_EXPORT QDir
{
protected:
- QDirPrivate *d_ptr;
+ QScopedPointer<QDirPrivate> d_ptr;
private:
Q_DECLARE_PRIVATE(QDir)
public:
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 551485d..1e3d5a3 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -109,6 +109,7 @@ QFilePrivate::openExternalFile(int flags, int fd)
return false;
#else
delete fileEngine;
+ fileEngine = 0;
QFSFileEngine *fe = new QFSFileEngine;
fe->setFileName(fileName);
fileEngine = fe;
@@ -125,6 +126,7 @@ QFilePrivate::openExternalFile(int flags, FILE *fh)
return false;
#else
delete fileEngine;
+ fileEngine = 0;
QFSFileEngine *fe = new QFSFileEngine;
fe->setFileName(fileName);
fileEngine = fe;
@@ -410,9 +412,6 @@ QFile::QFile(QFilePrivate &dd, QObject *parent)
QFile::~QFile()
{
close();
-#ifdef QT_NO_QOBJECT
- delete d_ptr;
-#endif
}
/*!
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index 96e0f82..b36fb69 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -439,8 +439,6 @@ QFileInfo::QFileInfo(const QFileInfo &fileinfo) : d_ptr(new QFileInfoPrivate(&fi
QFileInfo::~QFileInfo()
{
- delete d_ptr;
- d_ptr = 0;
}
/*!
diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h
index 97997a3..6c01f63 100644
--- a/src/corelib/io/qfileinfo.h
+++ b/src/corelib/io/qfileinfo.h
@@ -44,6 +44,7 @@
#include <QtCore/qfile.h>
#include <QtCore/qlist.h>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_HEADER
@@ -165,7 +166,7 @@ public:
#endif
protected:
- QFileInfoPrivate *d_ptr;
+ QScopedPointer<QFileInfoPrivate> d_ptr;
private:
Q_DECLARE_PRIVATE(QFileInfo)
};
diff --git a/src/corelib/io/qfilesystemwatcher_symbian.cpp b/src/corelib/io/qfilesystemwatcher_symbian.cpp
index b1a6188..aeb19db 100644
--- a/src/corelib/io/qfilesystemwatcher_symbian.cpp
+++ b/src/corelib/io/qfilesystemwatcher_symbian.cpp
@@ -80,7 +80,7 @@ void CNotifyChangeEvent::RunL()
if (iStatus.Int() == KErrNone){
fsSession.NotifyChange(ENotifyAll, iStatus, watchedPath);
SetActive();
- engine->emitPathChanged(this);
+ QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_LEAVE(engine->emitPathChanged(this));
} else {
qWarning("CNotifyChangeEvent::RunL() - Failed to order change notifications: %d", iStatus.Int());
}
@@ -262,9 +262,9 @@ void QSymbianFileSystemWatcherEngine::run()
void QSymbianFileSystemWatcherEngine::addNativeListener(const QString &directoryPath)
{
QMutexLocker locker(&mutex);
- HBufC* buffer = qt_QString2HBufCNewL(QDir::toNativeSeparators(directoryPath));
- currentEvent = CNotifyChangeEvent::New(fsSession, *buffer, this);
- delete buffer;
+ QString nativeDir(QDir::toNativeSeparators(directoryPath));
+ TPtrC ptr(qt_QString2TPtrC(nativeDir));
+ currentEvent = CNotifyChangeEvent::New(fsSession, ptr, this);
syncCondition.wakeOne();
}
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index e595f15..45e547f 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -404,23 +404,21 @@ bool QFSFileEngine::copy(const QString &newName)
TInt err = rfs.Connect();
if (err == KErrNone) {
CFileMan* fm = NULL;
- HBufC* oldBuf = NULL;
- HBufC* newBuf = NULL;
+ QString oldNative(QDir::toNativeSeparators(d->filePath));
+ TPtrC oldPtr(qt_QString2TPtrC(oldNative));
+ QFileInfo fi(newName);
+ QString absoluteNewName = fi.absolutePath() + QDir::separator() + fi.fileName();
+ QString newNative(QDir::toNativeSeparators(absoluteNewName));
+ TPtrC newPtr(qt_QString2TPtrC(newNative));
TRAP (err,
fm = CFileMan::NewL(rfs);
- oldBuf = qt_QString2HBufCNewL(QDir::toNativeSeparators(d->filePath));
RFile rfile;
- err = rfile.Open(rfs, *oldBuf, EFileShareReadersOrWriters);
+ err = rfile.Open(rfs, oldPtr, EFileShareReadersOrWriters);
if (err == KErrNone) {
- QFileInfo fi(newName);
- QString absoluteNewName = fi.absolutePath() + QDir::separator() + fi.fileName();
- newBuf = qt_QString2HBufCNewL(QDir::toNativeSeparators(absoluteNewName));
- err = fm->Copy(rfile, *newBuf);
+ err = fm->Copy(rfile, newPtr);
rfile.Close();
}
) // End TRAP
- delete oldBuf;
- delete newBuf;
delete fm;
rfs.Close();
}
@@ -675,10 +673,10 @@ static bool _q_isSymbianHidden(const QString &path, bool isDir)
if (isDir && absPath.at(absPath.size()-1) != QChar('/')) {
absPath += QChar('/');
}
- HBufC* buffer = qt_QString2HBufCNewL(QDir::toNativeSeparators(absPath));
+ QString native(QDir::toNativeSeparators(absPath));
+ TPtrC ptr(qt_QString2TPtrC(native));
TUint attributes;
- err = rfs.Att(*buffer, attributes);
- delete buffer;
+ err = rfs.Att(ptr, attributes);
rfs.Close();
if (err == KErrNone && (attributes & KEntryAttHidden)) {
retval = true;
diff --git a/src/corelib/io/qiodevice.h b/src/corelib/io/qiodevice.h
index 76d47ca..ad87125 100644
--- a/src/corelib/io/qiodevice.h
+++ b/src/corelib/io/qiodevice.h
@@ -46,6 +46,7 @@
#include <QtCore/qobject.h>
#else
#include <QtCore/qobjectdefs.h>
+#include <QtCore/qscopedpointer.h>
#endif
#include <QtCore/qstring.h>
@@ -160,7 +161,7 @@ protected:
void setErrorString(const QString &errorString);
#ifdef QT_NO_QOBJECT
- QIODevicePrivate *d_ptr;
+ QScopedPointer<QIODevicePrivate> d_ptr;
#endif
private:
diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp
index a59976c..26e7cdc 100644
--- a/src/corelib/io/qprocess_symbian.cpp
+++ b/src/corelib/io/qprocess_symbian.cpp
@@ -56,6 +56,7 @@
User::Panic(KQProcessPanic, panicReason); \
}
+#include <exception>
#include <e32base.h>
#include <e32std.h>
#include <stdio.h>
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index 1f77caa..0cbcc41 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -334,7 +334,6 @@ QResource::QResource(const QString &file, const QLocale &locale) : d_ptr(new QRe
*/
QResource::~QResource()
{
- delete d_ptr;
}
/*!
diff --git a/src/corelib/io/qresource.h b/src/corelib/io/qresource.h
index 1e9b2d5..f260b68 100644
--- a/src/corelib/io/qresource.h
+++ b/src/corelib/io/qresource.h
@@ -91,7 +91,7 @@ protected:
QStringList children() const;
protected:
- QResourcePrivate *d_ptr;
+ QScopedPointer<QResourcePrivate> d_ptr;
private:
Q_DECLARE_PRIVATE(QResource)
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index 6152518..afaaf28 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -1106,10 +1106,10 @@ static QString getPath(QSettings::Format format, QSettings::Scope scope)
QString homePath = QDir::homePath();
QString systemPath;
- globalMutex()->lock();
+ QMutexLocker locker(globalMutex());
PathHash *pathHash = pathHashFunc();
bool loadSystemPath = pathHash->isEmpty();
- globalMutex()->unlock();
+ locker.unlock();
if (loadSystemPath) {
/*
@@ -1121,7 +1121,7 @@ static QString getPath(QSettings::Format format, QSettings::Scope scope)
systemPath += QLatin1Char('/');
}
- QMutexLocker locker(globalMutex());
+ locker.relock();
if (pathHash->isEmpty()) {
/*
Lazy initialization of pathHash. We initialize the
@@ -1181,9 +1181,6 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format,
int i;
initFormat();
- for (i = 0; i < NumConfFiles; ++i)
- confFiles[i] = 0;
-
QString org = organization;
if (org.isEmpty()) {
setStatus(QSettings::AccessError);
@@ -1196,14 +1193,14 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format,
if (scope == QSettings::UserScope) {
QString userPath = getPath(format, QSettings::UserScope);
if (!application.isEmpty())
- confFiles[F_User | F_Application] = QConfFile::fromName(userPath + appFile, true);
- confFiles[F_User | F_Organization] = QConfFile::fromName(userPath + orgFile, true);
+ confFiles[F_User | F_Application].reset(QConfFile::fromName(userPath + appFile, true));
+ confFiles[F_User | F_Organization].reset(QConfFile::fromName(userPath + orgFile, true));
}
QString systemPath = getPath(format, QSettings::SystemScope);
if (!application.isEmpty())
- confFiles[F_System | F_Application] = QConfFile::fromName(systemPath + appFile, false);
- confFiles[F_System | F_Organization] = QConfFile::fromName(systemPath + orgFile, false);
+ confFiles[F_System | F_Application].reset(QConfFile::fromName(systemPath + appFile, false));
+ confFiles[F_System | F_Organization].reset(QConfFile::fromName(systemPath + orgFile, false));
for (i = 0; i < NumConfFiles; ++i) {
if (confFiles[i]) {
@@ -1222,9 +1219,7 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(const QString &fileName,
{
initFormat();
- confFiles[0] = QConfFile::fromName(fileName, true);
- for (int i = 1; i < NumConfFiles; ++i)
- confFiles[i] = 0;
+ confFiles[0].reset(QConfFile::fromName(fileName, true));
initAccess();
}
@@ -1241,19 +1236,27 @@ QConfFileSettingsPrivate::~QConfFileSettingsPrivate()
usedHash->remove(confFiles[i]->name);
if (confFiles[i]->size == 0) {
- delete confFiles[i];
+ delete confFiles[i].take();
} else if (unusedCache) {
- // compute a better size?
- unusedCache->insert(confFiles[i]->name, confFiles[i],
+ QT_TRY {
+ // compute a better size?
+ unusedCache->insert(confFiles[i]->name, confFiles[i].data(),
10 + (confFiles[i]->originalKeys.size() / 4));
+ confFiles[i].take();
+ } QT_CATCH(...) {
+ // out of memory. Do not cache the file.
+ delete confFiles[i].take();
+ }
}
}
+ // prevent the ScopedPointer to deref it again.
+ confFiles[i].take();
}
}
void QConfFileSettingsPrivate::remove(const QString &key)
{
- QConfFile *confFile = confFiles[spec];
+ QConfFile *confFile = confFiles[spec].data();
if (!confFile)
return;
@@ -1280,7 +1283,7 @@ void QConfFileSettingsPrivate::remove(const QString &key)
void QConfFileSettingsPrivate::set(const QString &key, const QVariant &value)
{
- QConfFile *confFile = confFiles[spec];
+ QConfFile *confFile = confFiles[spec].data();
if (!confFile)
return;
@@ -1297,7 +1300,7 @@ bool QConfFileSettingsPrivate::get(const QString &key, QVariant *value) const
bool found = false;
for (int i = 0; i < NumConfFiles; ++i) {
- if (QConfFile *confFile = confFiles[i]) {
+ if (QConfFile *confFile = confFiles[i].data()) {
QMutexLocker locker(&confFile->mutex);
if (!confFile->addedKeys.isEmpty()) {
@@ -1332,7 +1335,7 @@ QStringList QConfFileSettingsPrivate::children(const QString &prefix, ChildSpec
int startPos = prefix.size();
for (int i = 0; i < NumConfFiles; ++i) {
- if (QConfFile *confFile = confFiles[i]) {
+ if (QConfFile *confFile = confFiles[i].data()) {
QMutexLocker locker(&confFile->mutex);
if (thePrefix.isEmpty()) {
@@ -1365,7 +1368,7 @@ QStringList QConfFileSettingsPrivate::children(const QString &prefix, ChildSpec
void QConfFileSettingsPrivate::clear()
{
- QConfFile *confFile = confFiles[spec];
+ QConfFile *confFile = confFiles[spec].data();
if (!confFile)
return;
@@ -1381,7 +1384,7 @@ void QConfFileSettingsPrivate::sync()
// error we just try to go on and make the best of it
for (int i = 0; i < NumConfFiles; ++i) {
- QConfFile *confFile = confFiles[i];
+ QConfFile *confFile = confFiles[i].data();
if (confFile) {
QMutexLocker locker(&confFile->mutex);
syncConfFile(i);
@@ -1396,7 +1399,7 @@ void QConfFileSettingsPrivate::flush()
QString QConfFileSettingsPrivate::fileName() const
{
- QConfFile *confFile = confFiles[spec];
+ QConfFile *confFile = confFiles[spec].data();
if (!confFile)
return QString();
return confFile->name;
@@ -1407,7 +1410,7 @@ bool QConfFileSettingsPrivate::isWritable() const
if (format > QSettings::IniFormat && !writeFunc)
return false;
- QConfFile *confFile = confFiles[spec];
+ QConfFile *confFile = confFiles[spec].data();
if (!confFile)
return false;
@@ -1416,7 +1419,7 @@ bool QConfFileSettingsPrivate::isWritable() const
void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
{
- QConfFile *confFile = confFiles[confFileNo];
+ QConfFile *confFile = confFiles[confFileNo].data();
bool readOnly = confFile->addedKeys.isEmpty() && confFile->removedKeys.isEmpty();
bool ok;
@@ -2759,11 +2762,13 @@ QSettings::QSettings(const QString &fileName, Format format)
QSettings::~QSettings()
{
Q_D(QSettings);
- if (d->pendingChanges)
- d->flush();
-#ifdef QT_NO_QOBJECT
- delete d;
-#endif
+ if (d->pendingChanges) {
+ QT_TRY {
+ d->flush();
+ } QT_CATCH(...) {
+ ; // ok. then don't flush but at least don't throw in the destructor
+ }
+ }
}
/*!
@@ -3566,8 +3571,7 @@ void QSettings::setPath_helper(Scope scope, const QString &organization, const Q
QSettingsPrivate *oldPriv = d;
QSettingsPrivate *newPriv = QSettingsPrivate::create(oldPriv->format, scope, organization, application);
static_cast<QObjectPrivate &>(*newPriv) = static_cast<QObjectPrivate &>(*oldPriv); // copy the QObject stuff over (hack)
- delete oldPriv;
- d_ptr = newPriv;
+ d_ptr.reset(newPriv);
}
/*! \fn bool QSettings::writeEntry(const QString &key, bool value)
diff --git a/src/corelib/io/qsettings.h b/src/corelib/io/qsettings.h
index cbb24ba..41bce89 100644
--- a/src/corelib/io/qsettings.h
+++ b/src/corelib/io/qsettings.h
@@ -78,7 +78,7 @@ class Q_CORE_EXPORT QSettings
#ifndef QT_NO_QOBJECT
Q_OBJECT
#else
- QSettingsPrivate *d_ptr;
+ QScopedPointer<QSettingsPrivate> d_ptr;
#endif
Q_DECLARE_PRIVATE(QSettings)
diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h
index dd72fd9..1bdbf2c 100644
--- a/src/corelib/io/qsettings_p.h
+++ b/src/corelib/io/qsettings_p.h
@@ -300,7 +300,7 @@ private:
void ensureAllSectionsParsed(QConfFile *confFile) const;
void ensureSectionParsed(QConfFile *confFile, const QSettingsKey &key) const;
- QConfFile *confFiles[NumConfFiles];
+ QScopedSharedPointer<QConfFile> confFiles[NumConfFiles];
QSettings::ReadFunc readFunc;
QSettings::WriteFunc writeFunc;
QString extension;
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index 1167671..9382fae 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -1112,9 +1112,6 @@ QTextStream::~QTextStream()
#endif
if (!d->writeBuffer.isEmpty())
d->flushWriteBuffer();
-
- delete d;
- d_ptr = 0;
}
/*!
diff --git a/src/corelib/io/qtextstream.h b/src/corelib/io/qtextstream.h
index 6302d34..cfacec6 100644
--- a/src/corelib/io/qtextstream.h
+++ b/src/corelib/io/qtextstream.h
@@ -46,6 +46,7 @@
#include <QtCore/qstring.h>
#include <QtCore/qchar.h>
#include <QtCore/qlocale.h>
+#include <QtCore/qscopedpointer.h>
#ifndef QT_NO_TEXTCODEC
# ifdef QT3_SUPPORT
@@ -256,7 +257,7 @@ private:
Q_DISABLE_COPY(QTextStream)
- QTextStreamPrivate *d_ptr;
+ QScopedPointer<QTextStreamPrivate> d_ptr;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QTextStream::NumberFlags)
diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp
index 4f18490..101ed44 100644
--- a/src/corelib/kernel/qcore_symbian_p.cpp
+++ b/src/corelib/kernel/qcore_symbian_p.cpp
@@ -39,9 +39,11 @@
**
****************************************************************************/
+#include <exception>
#include <e32base.h>
#include <e32uid.h>
#include "qcore_symbian_p.h"
+#include <string>
QT_BEGIN_NAMESPACE
@@ -51,18 +53,17 @@ QT_BEGIN_NAMESPACE
must be deleted by the caller.
*/
-Q_CORE_EXPORT HBufC* qt_QString2HBufCNewL(const QString& aString)
+Q_CORE_EXPORT HBufC* qt_QString2HBufC(const QString& aString)
{
HBufC *buffer;
#ifdef QT_NO_UNICODE
TPtrC8 ptr(reinterpret_cast<const TUint8*>(aString.toLocal8Bit().constData()));
- buffer = HBufC8::NewL(ptr.Length());
- buffer->Des().Copy(ptr);
#else
- TPtrC16 ptr(reinterpret_cast<const TUint16*>(aString.utf16()));
- buffer = HBufC16::NewL(ptr.Length());
- buffer->Des().Copy(ptr);
+ TPtrC16 ptr(qt_QString2TPtrC(aString));
#endif
+ buffer = HBufC::New(ptr.Length());
+ Q_CHECK_PTR(buffer);
+ buffer->Des().Copy(ptr);
return buffer;
}
@@ -82,7 +83,8 @@ QHBufC::QHBufC()
QHBufC::QHBufC(const QHBufC &src)
{
- m_hBufC = src.m_hBufC->AllocL();
+ m_hBufC = src.m_hBufC->Alloc();
+ Q_CHECK_PTR(m_hBufC);
}
/*!
@@ -97,7 +99,7 @@ QHBufC::QHBufC(HBufC *src)
QHBufC::QHBufC(const QString &src)
{
- m_hBufC = qt_QString2HBufCNewL(src);
+ m_hBufC = qt_QString2HBufC(src);
}
QHBufC::~QHBufC()
@@ -172,4 +174,5 @@ Q_CORE_EXPORT TLibraryFunction qt_resolveS60PluginFunc(int ordinal)
return qt_s60_plugin_resolver()->resolve(ordinal);
}
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcore_symbian_p.h b/src/corelib/kernel/qcore_symbian_p.h
index 3b974c3..bd8f304 100644
--- a/src/corelib/kernel/qcore_symbian_p.h
+++ b/src/corelib/kernel/qcore_symbian_p.h
@@ -63,7 +63,7 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-Q_CORE_EXPORT HBufC* qt_QString2HBufCNewL(const QString& aString);
+Q_CORE_EXPORT HBufC* qt_QString2HBufC(const QString& aString);
Q_CORE_EXPORT QString qt_TDesC2QStringL(const TDesC& aDescriptor);
inline QString qt_TDes2QStringL(const TDes& aDescriptor) { return qt_TDesC2QStringL(aDescriptor); }
@@ -91,7 +91,7 @@ static inline TRect qt_QRect2TRect(const QRect& qr)
// Returned TPtrC is valid as long as the given parameter is valid and unmodified
static inline TPtrC qt_QString2TPtrC( const QString& string )
{
- return reinterpret_cast<const TUint16*>(string.utf16());
+ return TPtrC16(static_cast<const TUint16*>(string.utf16()), string.length());
}
class Q_CORE_EXPORT QHBufC
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index d99164b..5c3fd76 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -63,8 +63,10 @@
#include <private/qfactoryloader_p.h>
#ifdef Q_OS_SYMBIAN
+# include <exception>
# include <f32file.h>
# include "qeventdispatcher_symbian_p.h"
+# include "private/qcore_symbian_p.h"
#elif defined(Q_OS_UNIX)
# if !defined(QT_NO_GLIB)
# include "qeventdispatcher_glib_p.h"
@@ -88,6 +90,21 @@
QT_BEGIN_NAMESPACE
+class QLockedMutexUnlocker
+{
+public:
+ inline explicit QLockedMutexUnlocker(QMutex *m)
+ : mtx(m)
+ { }
+ inline ~QLockedMutexUnlocker() { unlock(); }
+ inline void unlock() { if (mtx) mtx->unlock(); mtx = 0; }
+
+private:
+ Q_DISABLE_COPY(QLockedMutexUnlocker)
+
+ QMutex *mtx;
+};
+
#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
extern QString qAppFileName();
#endif
@@ -159,7 +176,14 @@ void qRemovePostRoutine(QtCleanUpFunction p)
void Q_CORE_EXPORT qt_call_post_routines()
{
- QVFuncList *list = postRList();
+ QVFuncList *list = 0;
+ QT_TRY {
+ list = postRList();
+ } QT_CATCH(const std::bad_alloc &) {
+ // ignore - if we can't allocate a post routine list,
+ // there's a high probability that there's no post
+ // routine to be executed :)
+ }
if (!list)
return;
while (!list->isEmpty())
@@ -248,24 +272,26 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv)
QCoreApplicationPrivate::~QCoreApplicationPrivate()
{
+ if (threadData) {
#ifndef QT_NO_THREAD
- void *data = &threadData->tls;
- QThreadStorageData::finish((void **)data);
+ void *data = &threadData->tls;
+ QThreadStorageData::finish((void **)data);
#endif
- // need to clear the state of the mainData, just in case a new QCoreApplication comes along.
- QMutexLocker locker(&threadData->postEventList.mutex);
- for (int i = 0; i < threadData->postEventList.size(); ++i) {
- const QPostEvent &pe = threadData->postEventList.at(i);
- if (pe.event) {
- --pe.receiver->d_func()->postedEvents;
- pe.event->posted = false;
- delete pe.event;
+ // need to clear the state of the mainData, just in case a new QCoreApplication comes along.
+ QMutexLocker locker(&threadData->postEventList.mutex);
+ for (int i = 0; i < threadData->postEventList.size(); ++i) {
+ const QPostEvent &pe = threadData->postEventList.at(i);
+ if (pe.event) {
+ --pe.receiver->d_func()->postedEvents;
+ pe.event->posted = false;
+ delete pe.event;
+ }
}
+ threadData->postEventList.clear();
+ threadData->postEventList.recursion = 0;
+ threadData->quitNow = false;
}
- threadData->postEventList.clear();
- threadData->postEventList.recursion = 0;
- threadData->quitNow = false;
}
void QCoreApplicationPrivate::createEventDispatcher()
@@ -544,7 +570,14 @@ QCoreApplication::~QCoreApplication()
#if !defined(QT_NO_THREAD)
#if !defined(QT_NO_CONCURRENT)
// Synchronize and stop the global thread pool threads.
- QThreadPool::globalInstance()->waitForDone();
+ QThreadPool *globalThreadPool = 0;
+ QT_TRY {
+ globalThreadPool = QThreadPool::globalInstance();
+ } QT_CATCH (...) {
+ // swallow the exception, since destructors shouldn't throw
+ }
+ if (globalThreadPool)
+ globalThreadPool->waitForDone();
#endif
QThread::cleanup();
#endif
@@ -626,26 +659,13 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
d->inEventHandler = true;
#endif
-#if defined(Q_OS_SYMBIAN)
-// __UHEAP_MARK;
- TInt error;
- bool returnValue = false;
- TRAP(error, returnValue = notify(receiver, event));
- if (error != KErrNone) {
- qWarning(QString("Symbian OS error: %1").arg(error).toAscii().constData());
- }
-// __UHEAP_MARKEND;
-#elif defined(QT_NO_EXCEPTIONS)
- bool returnValue = notify(receiver, event);
-#else
bool returnValue;
- try {
+ QT_TRY {
returnValue = notify(receiver, event);
- } catch(...) {
+ } QT_CATCH (...) {
--threadData->loopLevel;
- throw;
+ QT_RETHROW;
}
-#endif
#ifdef QT_JAMBI_BUILD
// Restore the previous state if the object was not deleted..
@@ -1066,15 +1086,14 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
data->postEventList.mutex.lock();
}
+ QLockedMutexUnlocker locker(&data->postEventList.mutex);
+
// if this is one of the compressible events, do compression
if (receiver->d_func()->postedEvents
&& self && self->compressEvent(event, receiver, &data->postEventList)) {
- data->postEventList.mutex.unlock();
return;
}
- event->posted = true;
- ++receiver->d_func()->postedEvents;
if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {
// remember the current running eventloop for DeferredDelete
// events posted in the receiver's thread
@@ -1095,8 +1114,10 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
QPostEventList::iterator at = qUpperBound(begin, end, priority);
data->postEventList.insert(at, QPostEvent(receiver, event, priority));
}
+ event->posted = true;
+ ++receiver->d_func()->postedEvents;
data->canWait = false;
- data->postEventList.mutex.unlock();
+ locker.unlock();
if (data->eventDispatcher)
data->eventDispatcher->wakeUp();
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index 65733ac..095d501 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -195,6 +195,8 @@ private:
void init();
static QCoreApplication *self;
+
+ Q_DISABLE_COPY(QCoreApplication)
friend class QEventDispatcherUNIXPrivate;
friend class QApplication;
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp
index c5d91c2..423fbaa 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian.cpp
+++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp
@@ -193,7 +193,7 @@ void QWakeUpActiveObject::RunL()
{
iStatus = KRequestPending;
SetActive();
- m_dispatcher->wakeUpWasCalled();
+ QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_LEAVE(m_dispatcher->wakeUpWasCalled());
}
QTimerActiveObject::QTimerActiveObject(QEventDispatcherSymbian *dispatcher, SymbianTimerInfo *timerInfo)
@@ -222,9 +222,15 @@ void QTimerActiveObject::DoCancel()
void QTimerActiveObject::RunL()
{
- if (!okToRun())
- return;
+ int error;
+ QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_ERROR(error, Run());
+ if (error < 0) {
+ CActiveScheduler::Current()->Error(error); // stop and report here, as this timer will be deleted on scope exit
+ }
+}
+void QTimerActiveObject::Run()
+{
if (m_timerInfo->interval > 0) {
// Start a new timer immediately so that we don't lose time.
iStatus = KRequestPending;
@@ -240,7 +246,7 @@ void QTimerActiveObject::RunL()
SymbianTimerInfoPtr timerInfoPtr(m_timerInfo);
m_timerInfo->dispatcher->timerFired(m_timerInfo->timerId);
-
+
iStatus = KRequestPending;
SetActive();
TRequestStatus *status = &iStatus;
@@ -304,7 +310,7 @@ void QCompleteDeferredAOs::RunL()
iStatus = KRequestPending;
SetActive();
- m_dispatcher->reactivateDeferredActiveObjects();
+ QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_LEAVE(m_dispatcher->reactivateDeferredActiveObjects());
}
QSelectThread::QSelectThread()
@@ -577,7 +583,7 @@ void QSocketActiveObject::RunL()
if (!okToRun())
return;
- m_dispatcher->socketFired(this);
+ QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_LEAVE(m_dispatcher->socketFired(this));
}
void QSocketActiveObject::deleteLater()
@@ -633,101 +639,108 @@ void QEventDispatcherSymbian::closingDown()
bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags flags )
{
- Q_D(QAbstractEventDispatcher);
+ bool handledAnyEvent = false;
+ QT_TRY {
+ Q_D(QAbstractEventDispatcher);
+
// It is safe if this counter overflows. The main importance is that each
// iteration count is different from the last.
m_iterationCount++;
- RThread &thread = d->threadData->symbian_thread_handle;
-
- bool block;
- if (flags & QEventLoop::WaitForMoreEvents) {
- block = true;
- emit aboutToBlock();
- } else {
- block = false;
- }
-
- bool handledAnyEvent = false;
-
- bool oldNoSocketEventsValue = m_noSocketEvents;
- if (flags & QEventLoop::ExcludeSocketNotifiers) {
- m_noSocketEvents = true;
- } else {
- m_noSocketEvents = false;
- handledAnyEvent = sendDeferredSocketEvents();
- }
-
- bool handledSymbianEvent = false;
- m_interrupt = false;
-
- /*
- * This QTime variable is used to measure the time it takes to finish
- * the event loop. If we take too long in the loop, other processes
- * may be starved and killed. After the first event has completed, we
- * take the current time, and if the remaining events take longer than
- * a preset time, we temporarily lower the priority to force a context
- * switch. For applications that do not take unecessarily long in the
- * event loop, the priority will not be altered.
- */
- QTime time;
- enum {
- FirstRun,
- SubsequentRun,
- TimeStarted
- } timeState = FirstRun;
-
- TProcessPriority priority;
-
- while (1) {
- if (block) {
- // This is where Qt will spend most of its time.
- CActiveScheduler::Current()->WaitForAnyRequest();
+ RThread &thread = d->threadData->symbian_thread_handle;
+
+ bool block;
+ if (flags & QEventLoop::WaitForMoreEvents) {
+ block = true;
+ emit aboutToBlock();
} else {
- if (thread.RequestCount() == 0) {
- break;
- }
- // This one should return without delay.
- CActiveScheduler::Current()->WaitForAnyRequest();
- }
-
- if (timeState == SubsequentRun) {
- time.start();
- timeState = TimeStarted;
- }
-
- TInt error;
- handledSymbianEvent = CActiveScheduler::RunIfReady(error, CActive::EPriorityIdle);
- if (error) {
- qWarning("CActiveScheduler::RunIfReady() returned error: %i\n", error);
- CActiveScheduler::Current()->Error(error);
+ block = false;
}
- if (!handledSymbianEvent) {
- qFatal("QEventDispatcherSymbian::processEvents(): Caught Symbian stray signal");
- }
- handledAnyEvent = true;
- if (m_interrupt) {
- break;
+
+ bool oldNoSocketEventsValue = m_noSocketEvents;
+ if (flags & QEventLoop::ExcludeSocketNotifiers) {
+ m_noSocketEvents = true;
+ } else {
+ m_noSocketEvents = false;
+ handledAnyEvent = sendDeferredSocketEvents();
}
- block = false;
+
+ bool handledSymbianEvent = false;
+ m_interrupt = false;
+
+ /*
+ * This QTime variable is used to measure the time it takes to finish
+ * the event loop. If we take too long in the loop, other processes
+ * may be starved and killed. After the first event has completed, we
+ * take the current time, and if the remaining events take longer than
+ * a preset time, we temporarily lower the priority to force a context
+ * switch. For applications that do not take unecessarily long in the
+ * event loop, the priority will not be altered.
+ */
+ QTime time;
+ enum {
+ FirstRun,
+ SubsequentRun,
+ TimeStarted
+ } timeState = FirstRun;
+
+ TProcessPriority priority;
+
+ while (1) {
+ if (block) {
+ // This is where Qt will spend most of its time.
+ CActiveScheduler::Current()->WaitForAnyRequest();
+ } else {
+ if (thread.RequestCount() == 0) {
+ break;
+ }
+ // This one should return without delay.
+ CActiveScheduler::Current()->WaitForAnyRequest();
+ }
+
+ if (timeState == SubsequentRun) {
+ time.start();
+ timeState = TimeStarted;
+ }
+
+ TInt error;
+ handledSymbianEvent = CActiveScheduler::RunIfReady(error, CActive::EPriorityIdle);
+ if (error) {
+ qWarning("CActiveScheduler::RunIfReady() returned error: %i\n", error);
+ CActiveScheduler::Current()->Error(error);
+ }
+
+ if (!handledSymbianEvent) {
+ qFatal("QEventDispatcherSymbian::processEvents(): Caught Symbian stray signal");
+ }
+ handledAnyEvent = true;
+ if (m_interrupt) {
+ break;
+ }
+ block = false;
if (timeState == TimeStarted && time.elapsed() > 100) {
- priority = m_processHandle.Priority();
- m_processHandle.SetPriority(EPriorityLow);
- time.start();
- // Slight chance of race condition in the next lines, but nothing fatal
- // will happen, just wrong priority.
- if (m_processHandle.Priority() == EPriorityLow) {
- m_processHandle.SetPriority(priority);
+ priority = m_processHandle.Priority();
+ m_processHandle.SetPriority(EPriorityLow);
+ time.start();
+ // Slight chance of race condition in the next lines, but nothing fatal
+ // will happen, just wrong priority.
+ if (m_processHandle.Priority() == EPriorityLow) {
+ m_processHandle.SetPriority(priority);
+ }
}
- }
- if (timeState == FirstRun)
- timeState = SubsequentRun;
- };
-
- emit awake();
-
- m_noSocketEvents = oldNoSocketEventsValue;
+ if (timeState == FirstRun)
+ timeState = SubsequentRun;
+ };
+
+ emit awake();
+
+ m_noSocketEvents = oldNoSocketEventsValue;
+ } QT_CATCH (const std::exception& ex) {
+#ifndef QT_NO_EXCEPTIONS
+ CActiveScheduler::Current()->Error(qt_translateExceptionToSymbianError(ex));
+#endif
+ }
return handledAnyEvent;
}
diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h
index 64ea282..3593055 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian_p.h
+++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h
@@ -136,6 +136,9 @@ public:
protected:
void DoCancel();
void RunL();
+
+private:
+ void Run();
private:
SymbianTimerInfo *m_timerInfo;
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
index f7293d4..ea8299c 100644
--- a/src/corelib/kernel/qeventdispatcher_unix.cpp
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -184,7 +184,7 @@ int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags,
continue;
for (int i = 0; i < list.size(); ++i) {
- QSockNot *sn = list.at(i);
+ QSockNot *sn = list[i];
FD_ZERO(&fdset);
FD_SET(sn->fd, &fdset);
@@ -241,7 +241,7 @@ int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags,
for (int i=0; i<3; i++) {
QSockNotType::List &list = sn_vec[i].list;
for (int j = 0; j < list.size(); ++j) {
- QSockNot *sn = list.at(j);
+ QSockNot *sn = list[j];
if (FD_ISSET(sn->fd, &sn_vec[i].select_fds))
q->setSocketNotifierPending(sn->obj);
}
@@ -599,7 +599,10 @@ QEventDispatcherUNIX::QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObj
{ }
QEventDispatcherUNIX::~QEventDispatcherUNIX()
-{ }
+{
+ Q_D(QEventDispatcherUNIX);
+ d->threadData->eventDispatcher = 0;
+}
int QEventDispatcherUNIX::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
timeval *timeout)
@@ -706,8 +709,8 @@ QSockNotType::QSockNotType()
QSockNotType::~QSockNotType()
{
- while (!list.isEmpty())
- delete list.takeFirst();
+ for (int i = 0; i < list.size(); ++i)
+ delete list[i];
}
/*****************************************************************************
@@ -743,7 +746,7 @@ void QEventDispatcherUNIX::registerSocketNotifier(QSocketNotifier *notifier)
int i;
for (i = 0; i < list.size(); ++i) {
- QSockNot *p = list.at(i);
+ QSockNot *p = list[i];
if (p->fd < sockfd)
break;
if (p->fd == sockfd) {
@@ -781,7 +784,7 @@ void QEventDispatcherUNIX::unregisterSocketNotifier(QSocketNotifier *notifier)
QSockNot *sn = 0;
int i;
for (i = 0; i < list.size(); ++i) {
- sn = list.at(i);
+ sn = list[i];
if(sn->obj == notifier && sn->fd == sockfd)
break;
}
@@ -799,7 +802,7 @@ void QEventDispatcherUNIX::unregisterSocketNotifier(QSocketNotifier *notifier)
for (int i=0; i<3; i++) {
if (!d->sn_vec[i].list.isEmpty())
d->sn_highest = qMax(d->sn_highest, // list is fd-sorted
- d->sn_vec[i].list.first()->fd);
+ d->sn_vec[i].list[0]->fd);
}
}
}
@@ -823,7 +826,7 @@ void QEventDispatcherUNIX::setSocketNotifierPending(QSocketNotifier *notifier)
QSockNot *sn = 0;
int i;
for (i = 0; i < list.size(); ++i) {
- sn = list.at(i);
+ sn = list[i];
if(sn->obj == notifier && sn->fd == sockfd)
break;
}
diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
index 41329cf..816add5 100644
--- a/src/corelib/kernel/qeventdispatcher_unix_p.h
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -57,6 +57,7 @@
#include "QtCore/qlist.h"
#include "private/qabstracteventdispatcher_p.h"
#include "private/qpodlist_p.h"
+#include "QtCore/qvarlengtharray.h"
#include <sys/types.h>
#include <sys/time.h>
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 860180e..ac505e1 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -392,7 +392,9 @@ void QMetaObject::removeGuard(QObject **ptr)
if (!*ptr)
return;
GuardHash *hash = guardHash();
- if (!hash)
+ /* check that the hash is empty - otherwise we might detach
+ the shared_null hash, which will alloc, which is not nice */
+ if (!hash || hash->isEmpty())
return;
QMutexLocker locker(guardHashLock());
GuardHash::iterator it = hash->find(*ptr);
@@ -434,9 +436,19 @@ void QMetaObject::changeGuard(QObject **ptr, QObject *o)
*/
void QObjectPrivate::clearGuards(QObject *object)
{
- GuardHash *hash = guardHash();
- if (hash) {
- QMutexLocker locker(guardHashLock());
+ GuardHash *hash = 0;
+ QMutex *mutex = 0;
+ QT_TRY {
+ hash = guardHash();
+ mutex = guardHashLock();
+ } QT_CATCH(const std::bad_alloc &) {
+ // do nothing in case of OOM - code below is safe
+ }
+
+ /* check that the hash is empty - otherwise we might detach
+ the shared_null hash, which will alloc, which is not nice */
+ if (hash && !hash->isEmpty()) {
+ QMutexLocker locker(mutex);
GuardHash::iterator it = hash->find(object);
const GuardHash::iterator end = hash->end();
while (it.key() == object && it != end) {
@@ -754,7 +766,14 @@ QObject::~QObject()
QObjectPrivate::clearGuards(this);
}
- emit destroyed(this);
+ QT_TRY {
+ emit destroyed(this);
+ } QT_CATCH(...) {
+ // all the signal/slots connections are still in place - if we don't
+ // quit now, we will crash pretty soon.
+ qWarning("Detected an unexpected exception in ~QObject while emitting destroyed().");
+ QT_RETHROW;
+ }
{
QMutexLocker locker(&d->threadData->mutex);
@@ -853,9 +872,6 @@ QObject::~QObject()
objectName().isNull() ? "unnamed" : qPrintable(objectName()));
}
#endif
-
- delete d;
- d_ptr = 0;
}
@@ -1098,11 +1114,11 @@ bool QObject::event(QEvent *e)
#if defined(QT_NO_EXCEPTIONS)
mce->placeMetaCall(this);
#else
- try {
+ QT_TRY {
mce->placeMetaCall(this);
- } catch (...) {
+ } QT_CATCH(...) {
QObjectPrivate::resetCurrentSender(this, &currentSender, previousSender);
- throw;
+ QT_RETHROW;
}
#endif
QObjectPrivate::resetCurrentSender(this, &currentSender, previousSender);
@@ -3102,9 +3118,9 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal
#if defined(QT_NO_EXCEPTIONS)
receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
#else
- try {
+ QT_TRY {
receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
- } catch (...) {
+ } QT_CATCH(...) {
locker.relock();
QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
@@ -3113,7 +3129,7 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal
Q_ASSERT(connectionLists->inUse >= 0);
if (connectionLists->orphaned && !connectionLists->inUse)
delete connectionLists;
- throw;
+ QT_RETHROW;
}
#endif
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index dbec0a6..8d5c4e3 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -51,6 +51,7 @@
#ifdef QT_INCLUDE_COMPAT
#include <QtCore/qcoreevent.h>
#endif
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_HEADER
@@ -286,7 +287,7 @@ protected:
QObject(QObjectPrivate &dd, QObject *parent = 0);
protected:
- QObjectData *d_ptr;
+ QScopedPointer<QObjectData> d_ptr;
static const QMetaObject staticQtMetaObject;
diff --git a/src/corelib/kernel/qsharedmemory_symbian.cpp b/src/corelib/kernel/qsharedmemory_symbian.cpp
index b3b50e3..d05f9f3 100644
--- a/src/corelib/kernel/qsharedmemory_symbian.cpp
+++ b/src/corelib/kernel/qsharedmemory_symbian.cpp
@@ -116,11 +116,9 @@ bool QSharedMemoryPrivate::create(int size)
return false;
}
- HBufC* buffer = qt_QString2HBufCNewL(safeKey);
+ TPtrC ptr(qt_QString2TPtrC(safeKey));
- TInt err = chunk.CreateGlobal(*buffer, size, size);
-
- delete buffer;
+ TInt err = chunk.CreateGlobal(ptr, size, size);
setErrorString(function, err);
@@ -147,15 +145,11 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
return false;
}
- HBufC* buffer = qt_QString2HBufCNewL(safeKey);
+ TPtrC ptr(qt_QString2TPtrC(safeKey));
TInt err = KErrNoMemory;
- if (buffer) {
- err = chunk.OpenGlobal(*buffer, false);
- }
-
- delete buffer;
+ err = chunk.OpenGlobal(ptr, false);
if (err != KErrNone) {
setErrorString(function, err);
diff --git a/src/corelib/kernel/qsystemsemaphore.cpp b/src/corelib/kernel/qsystemsemaphore.cpp
index 7e09a6e..fb9385a 100644
--- a/src/corelib/kernel/qsystemsemaphore.cpp
+++ b/src/corelib/kernel/qsystemsemaphore.cpp
@@ -170,8 +170,8 @@ QT_BEGIN_NAMESPACE
\sa acquire(), key()
*/
QSystemSemaphore::QSystemSemaphore(const QString &key, int initialValue, AccessMode mode)
+ : d(new QSystemSemaphorePrivate)
{
- d = new QSystemSemaphorePrivate;
setKey(key, initialValue, mode);
}
@@ -193,7 +193,6 @@ QSystemSemaphore::QSystemSemaphore(const QString &key, int initialValue, AccessM
QSystemSemaphore::~QSystemSemaphore()
{
d->cleanHandle();
- delete d;
}
/*!
diff --git a/src/corelib/kernel/qsystemsemaphore.h b/src/corelib/kernel/qsystemsemaphore.h
index 5a02072..3cafebf 100644
--- a/src/corelib/kernel/qsystemsemaphore.h
+++ b/src/corelib/kernel/qsystemsemaphore.h
@@ -43,6 +43,7 @@
#define QSYSTEMSEMAPHORE_H
#include <QtCore/qstring.h>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_HEADER
@@ -89,7 +90,7 @@ public:
private:
Q_DISABLE_COPY(QSystemSemaphore)
- QSystemSemaphorePrivate *d;
+ QScopedPointer<QSystemSemaphorePrivate> d;
};
#endif // QT_NO_SYSTEMSEMAPHORE
diff --git a/src/corelib/kernel/qsystemsemaphore_symbian.cpp b/src/corelib/kernel/qsystemsemaphore_symbian.cpp
index cd5c3ff..8179046 100644
--- a/src/corelib/kernel/qsystemsemaphore_symbian.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_symbian.cpp
@@ -90,13 +90,12 @@ int QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode)
if (key.isEmpty())
return 0;
QString safeName = makeKeyFileName();
- HBufC* name = qt_QString2HBufCNewL(safeName);
+ TPtrC name(qt_QString2TPtrC(safeName));
int err;
- err = semaphore.OpenGlobal(*name,EOwnerProcess);
+ err = semaphore.OpenGlobal(name,EOwnerProcess);
if (err == KErrNotFound){
- err = semaphore.CreateGlobal(*name,initialValue, EOwnerProcess);
+ err = semaphore.CreateGlobal(name,initialValue, EOwnerProcess);
}
- delete name;
if (err){
setErrorString(QLatin1String("QSystemSemaphore::handle"),err);
return 0;
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 420dd1d..0ca0169 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -611,10 +611,10 @@ bool QLibraryPrivate::isPlugin(QSettings *settings)
.arg(fileName);
QStringList reg;
#ifndef QT_NO_SETTINGS
- bool madeSettings = false;
+ QScopedPointer<QSettings> madeSettings;
if (!settings) {
settings = new QSettings(QSettings::UserScope, QLatin1String("Trolltech"));
- madeSettings = true;
+ madeSettings.reset(settings);
}
reg = settings->value(regkey).toStringList();
#endif
@@ -708,8 +708,7 @@ bool QLibraryPrivate::isPlugin(QSettings *settings)
#endif
}
#ifndef QT_NO_SETTINGS
- if (madeSettings)
- delete settings;
+ madeSettings.reset();
#endif
if (!success) {
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index cb44a25..f1bdc64 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -163,9 +163,9 @@ QAdoptedThread::~QAdoptedThread()
QThread *QAdoptedThread::createThreadForAdoption()
{
- QThread *t = new QAdoptedThread(0);
- t->moveToThread(t);
- return t;
+ QScopedPointer<QThread> t(new QAdoptedThread(0));
+ t->moveToThread(t.data());
+ return t.take();
}
void QAdoptedThread::run()
@@ -483,10 +483,10 @@ uint QThread::stackSize() const
int QThread::exec()
{
Q_D(QThread);
- d->mutex.lock();
+ QMutexLocker locker(&d->mutex);
d->data->quitNow = false;
QEventLoop eventLoop;
- d->mutex.unlock();
+ locker.unlock();
int returnCode = eventLoop.exec();
return returnCode;
}
@@ -734,8 +734,9 @@ QThreadData* QThreadData::current()
{
static QThreadData *data = 0; // reinterpret_cast<QThreadData *>(pthread_getspecific(current_thread_data_key));
if (!data) {
- data = new QThreadData;
- data->thread = new QAdoptedThread(data);
+ QScopedPointer<QThreadData> newdata(new QThreadData);
+ newdata->thread = new QAdoptedThread(newdata.data());
+ data = newdata.take();
data->deref();
}
return data;
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 567c936..d2a824a 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -124,7 +124,14 @@ QThreadData *QThreadData::current()
} else {
data = new QThreadData;
pthread_setspecific(current_thread_data_key, data);
- data->thread = new QAdoptedThread(data);
+ QT_TRY {
+ data->thread = new QAdoptedThread(data);
+ } QT_CATCH(...) {
+ pthread_setspecific(current_thread_data_key, 0);
+ data->deref();
+ data = 0;
+ QT_RETHROW;
+ }
data->deref();
}
if (!QCoreApplicationPrivate::theMainThread)
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index 7094e3d..76e551e 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -112,7 +112,14 @@ QThreadData *QThreadData::current()
// This needs to be called prior to new AdoptedThread() to
// avoid recursion.
TlsSetValue(qt_current_thread_data_tls_index, threadData);
- threadData->thread = new QAdoptedThread(threadData);
+ QT_TRY {
+ threadData->thread = new QAdoptedThread(threadData);
+ } QT_CATCH(...) {
+ TlsSetValue(qt_current_thread_data_tls_index, 0);
+ threadData->deref();
+ threadData = 0;
+ QT_RETHROW;
+ }
threadData->deref();
}
diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp
index 35c55c1..4657009 100644
--- a/src/corelib/thread/qthreadstorage.cpp
+++ b/src/corelib/thread/qthreadstorage.cpp
@@ -101,12 +101,14 @@ void **QThreadStorageData::get() const
qWarning("QThreadStorage::get: QThreadStorage can only be used with threads started with QThread");
return 0;
}
- QMap<int, void *>::iterator it = data->tls.find(id);
+ QMap<int, void *>::const_iterator it = data->tls.constFind(id);
DEBUG_MSG("QThreadStorageData: Returning storage %d, data %p, for thread %p",
id,
it != data->tls.end() ? it.value() : 0,
data->thread);
- return it != data->tls.end() && it.value() != 0 ? &it.value() : 0;
+ // const_cast below is a bit evil - but we have to make sure not to detach here
+ // otherwise we'll go bonkers in oom situations
+ return it != data->tls.constEnd() && it.value() != 0 ? const_cast<void **>(&it.value()) : 0;
}
void **QThreadStorageData::set(void *p)
@@ -129,9 +131,9 @@ void **QThreadStorageData::set(void *p)
void *q = it.value();
it.value() = 0;
- mutex()->lock();
+ QMutexLocker locker(mutex());
void (*destructor)(void *) = destructors()->value(id);
- mutex()->unlock();
+ locker.unlock();
destructor(q);
}
@@ -167,9 +169,9 @@ void QThreadStorageData::finish(void **p)
continue;
}
- mutex()->lock();
+ QMutexLocker locker(mutex());
void (*destructor)(void *) = destructors()->value(id);
- mutex()->unlock();
+ locker.unlock();
if (!destructor) {
if (QThread::currentThread())
diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp
index a947ab5..7168a9a 100644
--- a/src/corelib/tools/qbitarray.cpp
+++ b/src/corelib/tools/qbitarray.cpp
@@ -209,6 +209,8 @@ void QBitArray::resize(int size)
uchar* c = reinterpret_cast<uchar*>(d.data());
if (size > (s << 3))
memset(c + s, 0, d.size() - s);
+ else if ( size % 8)
+ *(c+1+size/8) &= (1 << (size%8)) - 1;
*c = d.size()*8 - size;
}
}
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 6aa35f3..ae6561f 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -1233,14 +1233,11 @@ QByteArray::QByteArray(const char *str)
} else {
int len = qstrlen(str);
d = static_cast<Data *>(qMalloc(sizeof(Data)+len));
- if (!d) {
- d = &shared_null;
- } else {
- d->ref = 0;;
- d->alloc = d->size = len;
- d->data = d->array;
- memcpy(d->array, str, len+1); // include null terminator
- }
+ Q_CHECK_PTR(d);
+ d->ref = 0;;
+ d->alloc = d->size = len;
+ d->data = d->array;
+ memcpy(d->array, str, len+1); // include null terminator
}
d->ref.ref();
}
@@ -1264,15 +1261,12 @@ QByteArray::QByteArray(const char *data, int size)
d = &shared_empty;
} else {
d = static_cast<Data *>(qMalloc(sizeof(Data) + size));
- if (!d) {
- d = &shared_null;
- } else {
- d->ref = 0;
- d->alloc = d->size = size;
- d->data = d->array;
- memcpy(d->array, data, size);
- d->array[size] = '\0';
- }
+ Q_CHECK_PTR(d);
+ d->ref = 0;
+ d->alloc = d->size = size;
+ d->data = d->array;
+ memcpy(d->array, data, size);
+ d->array[size] = '\0';
}
d->ref.ref();
}
@@ -1290,15 +1284,12 @@ QByteArray::QByteArray(int size, char ch)
d = &shared_null;
} else {
d = static_cast<Data *>(qMalloc(sizeof(Data)+size));
- if (!d) {
- d = &shared_null;
- } else {
- d->ref = 0;
- d->alloc = d->size = size;
- d->data = d->array;
- d->array[size] = '\0';
- memset(d->array, ch, size);
- }
+ Q_CHECK_PTR(d);
+ d->ref = 0;
+ d->alloc = d->size = size;
+ d->data = d->array;
+ d->array[size] = '\0';
+ memset(d->array, ch, size);
}
d->ref.ref();
}
@@ -1334,8 +1325,7 @@ void QByteArray::resize(int size)
// QByteArray a(sz);
//
Data *x = static_cast<Data *>(qMalloc(sizeof(Data)+size));
- if (!x)
- return;
+ Q_CHECK_PTR(x);
x->ref = 1;
x->alloc = x->size = size;
x->data = x->array;
@@ -1377,8 +1367,7 @@ void QByteArray::realloc(int alloc)
{
if (d->ref != 1 || d->data != d->array) {
Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc));
- if (!x)
- return;
+ Q_CHECK_PTR(x);
x->size = qMin(alloc, d->size);
::memcpy(x->array, d->data, x->size);
x->array[x->size] = '\0';
@@ -1390,8 +1379,7 @@ void QByteArray::realloc(int alloc)
d = x;
} else {
Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc));
- if (!x)
- return;
+ Q_CHECK_PTR(x);
x->alloc = alloc;
x->data = x->array;
d = x;
@@ -1812,11 +1800,13 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
const char *b = before;
if (after >= d->data && after < d->data + d->size) {
char *copy = (char *)malloc(asize);
+ Q_CHECK_PTR(copy);
memcpy(copy, after, asize);
a = copy;
}
if (before >= d->data && before < d->data + d->size) {
char *copy = (char *)malloc(bsize);
+ Q_CHECK_PTR(copy);
memcpy(copy, before, bsize);
b = copy;
}
@@ -3738,6 +3728,7 @@ QByteArray QByteArray::number(double n, char f, int prec)
QByteArray QByteArray::fromRawData(const char *data, int size)
{
Data *x = static_cast<Data *>(qMalloc(sizeof(Data)));
+ Q_CHECK_PTR(x);
if (data) {
x->data = const_cast<char *>(data);
} else {
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 781514c..b43891c 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -2200,8 +2200,8 @@ int QTime::elapsed() const
\sa isValid()
*/
QDateTime::QDateTime()
+ : d(new QDateTimePrivate)
{
- d = new QDateTimePrivate;
}
@@ -2211,8 +2211,8 @@ QDateTime::QDateTime()
*/
QDateTime::QDateTime(const QDate &date)
+ : d(new QDateTimePrivate)
{
- d = new QDateTimePrivate;
d->date = date;
d->time = QTime(0, 0, 0);
}
@@ -2225,8 +2225,8 @@ QDateTime::QDateTime(const QDate &date)
*/
QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
+ : d(new QDateTimePrivate)
{
- d = new QDateTimePrivate;
d->date = date;
d->time = date.isValid() && !time.isValid() ? QTime(0, 0, 0) : time;
d->spec = (spec == Qt::UTC) ? QDateTimePrivate::UTC : QDateTimePrivate::LocalUnknown;
@@ -2237,8 +2237,8 @@ QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
*/
QDateTime::QDateTime(const QDateTime &other)
+ : d(other.d.data())
{
- d = other.d;
d->ref.ref();
}
@@ -2247,8 +2247,6 @@ QDateTime::QDateTime(const QDateTime &other)
*/
QDateTime::~QDateTime()
{
- if (!d->ref.deref())
- delete d;
}
/*!
@@ -2258,7 +2256,7 @@ QDateTime::~QDateTime()
QDateTime &QDateTime::operator=(const QDateTime &other)
{
- qAtomicAssign(d, other.d);
+ d.assign(other.d.data());
return *this;
}
@@ -3298,7 +3296,7 @@ QDateTime QDateTime::fromString(const QString &string, const QString &format)
*/
void QDateTime::detach()
{
- qAtomicDetach(d);
+ d.detach();
}
/*****************************************************************************
diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
index 3278297..cf4246d 100644
--- a/src/corelib/tools/qdatetime.h
+++ b/src/corelib/tools/qdatetime.h
@@ -44,6 +44,7 @@
#include <QtCore/qstring.h>
#include <QtCore/qnamespace.h>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_HEADER
@@ -284,7 +285,7 @@ public:
private:
friend class QDateTimePrivate;
void detach();
- QDateTimePrivate *d;
+ QScopedSharedPointer<QDateTimePrivate> d;
#ifndef QT_NO_DATASTREAM
friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &);
diff --git a/src/corelib/tools/qharfbuzz.cpp b/src/corelib/tools/qharfbuzz.cpp
index 1940209..923eda4 100644
--- a/src/corelib/tools/qharfbuzz.cpp
+++ b/src/corelib/tools/qharfbuzz.cpp
@@ -126,6 +126,7 @@ char *HB_TextCodec_ConvertFromUnicode(void *codec, const HB_UChar16 *unicode, hb
QByteArray data = reinterpret_cast<QTextCodec *>(codec)->fromUnicode((const QChar *)unicode, length);
// ### suboptimal
char *output = (char *)malloc(data.length() + 1);
+ Q_CHECK_PTR(output);
memcpy(output, data.constData(), data.length() + 1);
if (outputLength)
*outputLength = data.length();
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index 2313e0e..a703621 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -171,7 +171,9 @@ QHashData QHashData::shared_null = {
void *QHashData::allocateNode()
{
- return qMalloc(nodeSize);
+ void *ptr = qMalloc(nodeSize);
+ Q_CHECK_PTR(ptr);
+ return ptr;
}
void QHashData::freeNode(void *node)
@@ -181,6 +183,13 @@ void QHashData::freeNode(void *node)
QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize)
{
+ return detach_helper( node_duplicate, 0, nodeSize );
+}
+
+QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *),
+ void (*node_delete)(Node *),
+ int nodeSize)
+{
union {
QHashData *d;
Node *e;
@@ -197,18 +206,43 @@ QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *), int
d->sharable = true;
if (numBuckets) {
- d->buckets = new Node *[numBuckets];
+ QT_TRY {
+ d->buckets = new Node *[numBuckets];
+ } QT_CATCH(...) {
+ // restore a consistent state for d
+ d->numBuckets = 0;
+ // roll back
+ d->free_helper(node_delete);
+ QT_RETHROW;
+ }
+
Node *this_e = reinterpret_cast<Node *>(this);
for (int i = 0; i < numBuckets; ++i) {
Node **nextNode = &d->buckets[i];
Node *oldNode = buckets[i];
while (oldNode != this_e) {
- Node *dup = static_cast<Node *>(allocateNode());
- node_duplicate(oldNode, dup);
- dup->h = oldNode->h;
- *nextNode = dup;
- nextNode = &dup->next;
- oldNode = oldNode->next;
+ QT_TRY {
+ Node *dup = static_cast<Node *>(allocateNode());
+
+ QT_TRY {
+ node_duplicate(oldNode, dup);
+ } QT_CATCH(...) {
+ freeNode( dup );
+ QT_RETHROW;
+ }
+
+ dup->h = oldNode->h;
+ *nextNode = dup;
+ nextNode = &dup->next;
+ oldNode = oldNode->next;
+ } QT_CATCH(...) {
+ // restore a consistent state for d
+ *nextNode = e;
+ d->numBuckets = i+1;
+ // roll back
+ d->free_helper(node_delete);
+ QT_RETHROW;
+ }
}
*nextNode = e;
}
@@ -216,6 +250,26 @@ QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *), int
return d;
}
+void QHashData::free_helper(void (*node_delete)(Node *))
+{
+ if (node_delete) {
+ Node *this_e = reinterpret_cast<Node *>(this);
+ Node **bucket = reinterpret_cast<Node **>(this->buckets);
+
+ int n = numBuckets;
+ while (n--) {
+ Node *cur = *bucket++;
+ while (cur != this_e) {
+ Node *next = cur->next;
+ node_delete(cur);
+ cur = next;
+ }
+ }
+ }
+ delete [] buckets;
+ delete this;
+}
+
QHashData::Node *QHashData::nextNode(Node *node)
{
union {
@@ -298,9 +352,10 @@ void QHashData::rehash(int hint)
Node **oldBuckets = buckets;
int oldNumBuckets = numBuckets;
+ int nb = primeForNumBits(hint);
+ buckets = new Node *[nb];
numBits = hint;
- numBuckets = primeForNumBits(hint);
- buckets = new Node *[numBuckets];
+ numBuckets = nb;
for (int i = 0; i < numBuckets; ++i)
buckets[i] = e;
@@ -327,8 +382,7 @@ void QHashData::rehash(int hint)
void QHashData::destroyAndFree()
{
- delete [] buckets;
- delete this;
+ free_helper(0);
}
#ifdef QT_QHASH_DEBUG
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 41b4794..b3f82e9 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -129,12 +129,15 @@ struct Q_CORE_EXPORT QHashData
void *allocateNode();
void freeNode(void *node);
- QHashData *detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize);
+ QHashData *detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize); // ### Qt5 remove me
+ QHashData *detach_helper(void (*node_duplicate)(Node *, void *), void (*node_delete)(Node *),
+ int nodeSize);
void mightGrow();
bool willGrow();
void hasShrunk();
void rehash(int hint);
- void destroyAndFree();
+ void free_helper(void (*node_delete)(Node *));
+ void destroyAndFree(); // ### Qt5 remove me
Node *firstNode();
#ifdef QT_QHASH_DEBUG
void dump();
@@ -476,21 +479,30 @@ private:
Node **findNode(const Key &key, uint *hp = 0) const;
Node *createNode(uint h, const Key &key, const T &value, Node **nextNode);
void deleteNode(Node *node);
+ static void deleteNode(QHashData::Node *node);
static void duplicateNode(QHashData::Node *originalNode, void *newNode);
};
+
template <class Key, class T>
Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode(Node *node)
{
+ deleteNode(reinterpret_cast<QHashData::Node*>(node));
+}
+
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode(QHashData::Node *node)
+{
#ifdef Q_CC_BOR
- node->~QHashNode<Key, T>();
+ concrete(node)->~QHashNode<Key, T>();
#elif defined(QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION)
- node->~QHashNode();
+ concrete(node)->~QHashNode();
#else
- node->~Node();
+ concrete(node)->~Node();
#endif
- d->freeNode(node);
+ qFree(node);
}
template <class Key, class T>
@@ -538,18 +550,7 @@ Q_INLINE_TEMPLATE QHash<Key, T> &QHash<Key, T>::unite(const QHash<Key, T> &other
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::freeData(QHashData *x)
{
- Node *e_for_x = reinterpret_cast<Node *>(x);
- Node **bucket = reinterpret_cast<Node **>(x->buckets);
- int n = x->numBuckets;
- while (n--) {
- Node *cur = *bucket++;
- while (cur != e_for_x) {
- Node *next = cur->next;
- deleteNode(cur);
- cur = next;
- }
- }
- x->destroyAndFree();
+ x->free_helper(deleteNode);
}
template <class Key, class T>
@@ -561,7 +562,7 @@ Q_INLINE_TEMPLATE void QHash<Key, T>::clear()
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::detach_helper()
{
- QHashData *x = d->detach_helper(duplicateNode,
+ QHashData *x = d->detach_helper(duplicateNode, deleteNode,
QTypeInfo<T>::isDummy ? sizeof(DummyNode) : sizeof(Node));
if (!d->ref.deref())
freeData(d);
diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h
index 6a85386..79311bc 100644
--- a/src/corelib/tools/qlinkedlist.h
+++ b/src/corelib/tools/qlinkedlist.h
@@ -265,15 +265,22 @@ void QLinkedList<T>::detach_helper()
x.d->ref = 1;
x.d->size = d->size;
x.d->sharable = true;
- Node *i = e->n, *j = x.e;
- while (i != e) {
- j->n = new Node(i->t);
- j->n->p = j;
- i = i->n;
- j = j->n;
+ Node *original = e->n;
+ Node *copy = x.e;
+ while (original != e) {
+ QT_TRY {
+ copy->n = new Node(original->t);
+ copy->n->p = copy;
+ original = original->n;
+ copy = copy->n;
+ } QT_CATCH(...) {
+ copy->n = x.e;
+ free(x.d);
+ QT_RETHROW;
+ }
}
- j->n = x.e;
- x.e->p = j;
+ copy->n = x.e;
+ x.e->p = copy;
if (!d->ref.deref())
free(d);
d = x.d;
@@ -474,14 +481,21 @@ QLinkedList<T> &QLinkedList<T>::operator+=(const QLinkedList<T> &l)
detach();
int n = l.d->size;
d->size += n;
- Node *o = l.e->n;
+ Node *original = l.e->n;
while (n--) {
- Node *i = new Node(o->t);
- o = o->n;
- i->n = e;
- i->p = e->p;
- i->p->n = i;
- e->p = i;
+ QT_TRY {
+ Node *copy = new Node(original->t);
+ original = original->n;
+ copy->n = e;
+ copy->p = e->p;
+ copy->p->n = copy;
+ e->p = copy;
+ } QT_CATCH(...) {
+ // restore the original list
+ while (n++<d->size)
+ removeLast();
+ QT_RETHROW;
+ }
}
return *this;
}
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 3c21ec1..89e082b 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -117,6 +117,7 @@ public:
inline int size() const { return p.size(); }
inline void detach() { if (d->ref != 1) detach_helper(); }
+ inline void detachShared() { if (d->ref != 1 && d != &QListData::shared_null) detach_helper(); }
inline bool isDetached() const { return d->ref == 1; }
inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
@@ -352,12 +353,27 @@ Q_INLINE_TEMPLATE void QList<T>::node_destruct(Node *n)
template <typename T>
Q_INLINE_TEMPLATE void QList<T>::node_copy(Node *from, Node *to, Node *src)
{
- if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic)
- while(from != to)
- (from++)->v = new T(*reinterpret_cast<T*>((src++)->v));
- else if (QTypeInfo<T>::isComplex)
- while(from != to)
- new (from++) T(*reinterpret_cast<T*>(src++));
+ Node *current = from;
+ if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
+ QT_TRY {
+ while(current != to)
+ (current++)->v = new T(*reinterpret_cast<T*>((src++)->v));
+ } QT_CATCH(...) {
+ while (current != from)
+ delete reinterpret_cast<T*>(current--);
+ QT_RETHROW;
+ }
+ }
+ else if (QTypeInfo<T>::isComplex) {
+ QT_TRY {
+ while(current != to)
+ new (current++) T(*reinterpret_cast<T*>(src++));
+ } QT_CATCH(...) {
+ while (current != from)
+ (reinterpret_cast<T*>(current--))->~T();
+ QT_RETHROW;
+ }
+ }
}
template <typename T>
@@ -384,8 +400,16 @@ Q_INLINE_TEMPLATE QList<T> &QList<T>::operator=(const QList<T> &l)
}
template <typename T>
inline typename QList<T>::iterator QList<T>::insert(iterator before, const T &t)
-{ Node *n = reinterpret_cast<Node *>(p.insert(before.i-reinterpret_cast<Node *>(p.begin())));
- node_construct(n,t); return n; }
+{
+ Node *n = reinterpret_cast<Node *>(p.insert(before.i - reinterpret_cast<Node *>(p.begin())));
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ p.remove(before.i - reinterpret_cast<Node *>(p.begin()));
+ QT_RETHROW;
+ }
+ return n;
+}
template <typename T>
inline typename QList<T>::iterator QList<T>::erase(iterator it)
{ node_destruct(it.i);
@@ -423,10 +447,22 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t)
{
detach();
if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
- node_construct(reinterpret_cast<Node *>(p.append()), t);
+ Node *n = reinterpret_cast<Node *>(p.append());
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ --d->end;
+ QT_RETHROW;
+ }
} else {
const T cpy(t);
- node_construct(reinterpret_cast<Node *>(p.append()), cpy);
+ Node *n = reinterpret_cast<Node *>(p.append());
+ QT_TRY {
+ node_construct(n, cpy);
+ } QT_CATCH(...) {
+ --d->end;
+ QT_RETHROW;
+ }
}
}
@@ -435,10 +471,22 @@ inline void QList<T>::prepend(const T &t)
{
detach();
if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
- node_construct(reinterpret_cast<Node *>(p.prepend()), t);
+ Node *n = reinterpret_cast<Node *>(p.prepend());
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ ++d->begin;
+ QT_RETHROW;
+ }
} else {
const T cpy(t);
- node_construct(reinterpret_cast<Node *>(p.prepend()), cpy);
+ Node *n = reinterpret_cast<Node *>(p.prepend());
+ QT_TRY {
+ node_construct(n, cpy);
+ } QT_CATCH(...) {
+ ++d->begin;
+ QT_RETHROW;
+ }
}
}
@@ -447,10 +495,22 @@ inline void QList<T>::insert(int i, const T &t)
{
detach();
if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
- node_construct(reinterpret_cast<Node *>(p.insert(i)), t);
+ Node *n = reinterpret_cast<Node *>(p.insert(i));
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ p.remove(i);
+ QT_RETHROW;
+ }
} else {
const T cpy(t);
- node_construct(reinterpret_cast<Node *>(p.insert(i)), cpy);
+ Node *n = reinterpret_cast<Node *>(p.insert(i));
+ QT_TRY {
+ node_construct(n, cpy);
+ } QT_CATCH(...) {
+ p.remove(i);
+ QT_RETHROW;
+ }
}
}
@@ -522,7 +582,14 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper()
{
Node *n = reinterpret_cast<Node *>(p.begin());
QListData::Data *x = p.detach2();
- node_copy(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.end()), n);
+ QT_TRY {
+ node_copy(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.end()), n);
+ } QT_CATCH(...) {
+ qFree(d);
+ d = x;
+ QT_RETHROW;
+ }
+
if (!x->ref.deref())
free(x);
}
@@ -572,7 +639,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::clear()
template <typename T>
Q_OUTOFLINE_TEMPLATE int QList<T>::removeAll(const T &_t)
{
- detach();
+ detachShared();
const T t = _t;
int removedCount=0, i=0;
Node *n;
@@ -590,7 +657,7 @@ Q_OUTOFLINE_TEMPLATE int QList<T>::removeAll(const T &_t)
template <typename T>
Q_OUTOFLINE_TEMPLATE bool QList<T>::removeOne(const T &_t)
{
- detach();
+ detachShared();
int index = indexOf(_t);
if (index != -1) {
removeAt(index);
diff --git a/src/corelib/tools/qlistdata.cpp b/src/corelib/tools/qlistdata.cpp
index 34a5d80..efdde64 100644
--- a/src/corelib/tools/qlistdata.cpp
+++ b/src/corelib/tools/qlistdata.cpp
@@ -39,6 +39,7 @@
**
****************************************************************************/
+#include <new>
#include "qlist.h"
#include "qtools_p.h"
#include <string.h>
@@ -71,8 +72,7 @@ static int grow(int size)
QListData::Data *QListData::detach()
{
Data *x = static_cast<Data *>(qMalloc(DataHeaderSize + d->alloc * sizeof(void *)));
- if (!x)
- qFatal("QList: Out of memory");
+ Q_CHECK_PTR(x);
::memcpy(x, d, DataHeaderSize + d->alloc * sizeof(void *));
x->alloc = d->alloc;
@@ -91,10 +91,10 @@ QListData::Data *QListData::detach()
QListData::Data *QListData::detach2()
{
Data *x = d;
- d = static_cast<Data *>(qMalloc(DataHeaderSize + x->alloc * sizeof(void *)));
- if (!d)
- qFatal("QList: Out of memory");
+ Data* t = static_cast<Data *>(qMalloc(DataHeaderSize + x->alloc * sizeof(void *)));
+ Q_CHECK_PTR(t);
+ d = t;
::memcpy(d, x, DataHeaderSize + x->alloc * sizeof(void *));
d->alloc = x->alloc;
d->ref = 1;
@@ -109,8 +109,7 @@ void QListData::realloc(int alloc)
{
Q_ASSERT(d->ref == 1);
Data *x = static_cast<Data *>(qRealloc(d, DataHeaderSize + alloc * sizeof(void *)));
- if (!x)
- qFatal("QList: Out of memory");
+ Q_CHECK_PTR(x);
d = x;
d->alloc = alloc;
@@ -514,6 +513,15 @@ void **QListData::erase(void **xi)
\internal
*/
+/*! \fn void QList::detachShared()
+
+ \internal
+
+ like detach(), but does nothing if we're shared_null.
+ This prevents needless mallocs, and makes QList more exception safe
+ in case of cleanup work done in destructors on empty lists.
+*/
+
/*! \fn bool QList::isDetached() const
\internal
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 4d042ae..4317933 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -5124,6 +5124,7 @@ static Bigint *Balloc(int k)
x = 1 << k;
rv = static_cast<Bigint *>(MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long)));
+ Q_CHECK_PTR(rv);
rv->k = k;
rv->maxwds = x;
rv->sign = rv->wds = 0;
@@ -6788,6 +6789,7 @@ static char *_qdtoa( NEEDS_VOLATILE double d, int mode, int ndigits, int *decpt,
i = 1;
}
*resultp = static_cast<char *>(malloc(i + 1));
+ Q_CHECK_PTR(resultp);
s = s0 = *resultp;
if (ilim >= 0 && ilim <= Quick_max && try_quick) {
@@ -7209,6 +7211,7 @@ Q_CORE_EXPORT char *qdtoa( double d, int mode, int ndigits, int *decpt, int *sig
n = i + 1;
}
*resultp = static_cast<char*>(malloc(n + 1));
+ Q_CHECK_PTR(resultp);
qstrncpy(*resultp, res, n + 1);
return *resultp;
}
diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp
index 07df28d..ceaf370 100644
--- a/src/corelib/tools/qmap.cpp
+++ b/src/corelib/tools/qmap.cpp
@@ -59,6 +59,7 @@ QMapData QMapData::shared_null = {
QMapData *QMapData::createData()
{
QMapData *d = new QMapData;
+ Q_CHECK_PTR(d);
Node *e = reinterpret_cast<Node *>(d);
e->backward = e;
e->forward[0] = e;
@@ -84,6 +85,15 @@ void QMapData::continueFreeData(int offset)
delete this;
}
+/*!
+ Creates a new node inside the data structure.
+
+ \a update is an array with pointers to the node after which the new node
+ should be inserted. Because of the strange skip list data structure there
+ could be several pointers to this node on different levels.
+ \a offset is an amount of bytes that needs to reserved just before the
+ QMapData::Node structure.
+*/
QMapData::Node *QMapData::node_create(Node *update[], int offset)
{
int level = 0;
@@ -94,10 +104,6 @@ QMapData::Node *QMapData::node_create(Node *update[], int offset)
mask <<= Sparseness;
}
- ++randomBits;
- if (level == 3 && !insertInOrder)
- randomBits = qrand();
-
if (level > topLevel) {
Node *e = reinterpret_cast<Node *>(this);
level = ++topLevel;
@@ -105,7 +111,13 @@ QMapData::Node *QMapData::node_create(Node *update[], int offset)
update[level] = e;
}
+ ++randomBits;
+ if (level == 3 && !insertInOrder)
+ randomBits = qrand();
+
void *concreteNode = qMalloc(offset + sizeof(Node) + level * sizeof(Node *));
+ Q_CHECK_PTR(concreteNode);
+
Node *abstractNode = reinterpret_cast<Node *>(reinterpret_cast<char *>(concreteNode) + offset);
abstractNode->backward = update[0];
@@ -116,6 +128,7 @@ QMapData::Node *QMapData::node_create(Node *update[], int offset)
update[i]->forward[i] = abstractNode;
update[i] = abstractNode;
}
+ // update[level+1]=reinterpret_cast<Node *>(this);
++size;
return abstractNode;
}
@@ -146,7 +159,7 @@ uint QMapData::adjust_ptr(Node *node)
void QMapData::dump()
{
- qDebug("Map data (ref = %d, size = %d, randomBits = %#.8x)", ref.atomic, size, randomBits);
+ qDebug("Map data (ref = %d, size = %d, randomBits = %#.8x)", int(ref), size, randomBits);
QString preOutput;
QVector<QString> output(topLevel + 1);
@@ -158,12 +171,12 @@ void QMapData::dump()
Node *update[LastLevel + 1];
for (int i = 0; i <= topLevel; ++i) {
- str.sprintf("%d: [%.8x] -", i, adjust_ptr(forward[i]));
+ str.sprintf("%d: [%.8x] -", i, adjust_ptr(reinterpret_cast<Node *>(forward[i])));
output[i] += str;
- update[i] = forward[i];
+ update[i] = reinterpret_cast<Node *>(forward[i]);
}
- Node *node = forward[0];
+ Node *node = reinterpret_cast<Node *>(forward[0]);
while (node != e) {
int level = 0;
while (level < topLevel && update[level + 1] == node)
@@ -178,13 +191,13 @@ void QMapData::dump()
update[i] = node->forward[i];
}
for (int j = level + 1; j <= topLevel; ++j)
- output[j] += "---------------";
+ output[j] += QString("---------------");
node = node->forward[0];
}
- qDebug(preOutput.ascii());
+ qDebug("%s", preOutput.ascii());
for (int i = 0; i <= topLevel; ++i)
- qDebug(output[i].ascii());
+ qDebug("%s", output[i].ascii());
}
#endif
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index 0215a78..bd9ba74 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -416,9 +416,29 @@ Q_INLINE_TEMPLATE typename QMapData::Node *
QMap<Key, T>::node_create(QMapData *adt, QMapData::Node *aupdate[], const Key &akey, const T &avalue)
{
QMapData::Node *abstractNode = adt->node_create(aupdate, payload());
- Node *concreteNode = concrete(abstractNode);
- new (&concreteNode->key) Key(akey);
- new (&concreteNode->value) T(avalue);
+ QT_TRY {
+ Node *concreteNode = concrete(abstractNode);
+ new (&concreteNode->key) Key(akey);
+ QT_TRY {
+ new (&concreteNode->value) T(avalue);
+ } QT_CATCH(...) {
+ concreteNode->key.~Key();
+ QT_RETHROW;
+ }
+ } QT_CATCH(...) {
+ adt->node_delete(aupdate, payload(), abstractNode);
+ QT_RETHROW;
+ }
+
+ // clean up the update array for further insertions
+ /*
+ for (int i = 0; i <= d->topLevel; ++i) {
+ if ( aupdate[i]==reinterpret_cast<QMapData::Node *>(adt) || aupdate[i]->forward[i] != abstractNode)
+ break;
+ aupdate[i] = abstractNode;
+ }
+*/
+
return abstractNode;
}
@@ -704,8 +724,13 @@ Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::detach_helper()
QMapData::Node *cur = e->forward[0];
update[0] = x.e;
while (cur != e) {
- Node *concreteNode = concrete(cur);
- node_create(x.d, update, concreteNode->key, concreteNode->value);
+ QT_TRY {
+ Node *concreteNode = concrete(cur);
+ node_create(x.d, update, concreteNode->key, concreteNode->value);
+ } QT_CATCH(...) {
+ freeData(x.d);
+ QT_RETHROW;
+ }
cur = cur->forward[0];
}
x.d->insertInOrder = false;
diff --git a/src/corelib/tools/qpodlist_p.h b/src/corelib/tools/qpodlist_p.h
index 9708f8d..9e6d19b 100644
--- a/src/corelib/tools/qpodlist_p.h
+++ b/src/corelib/tools/qpodlist_p.h
@@ -53,9 +53,7 @@
// We mean it.
//
-#include <QtCore/qcontainerfwd.h>
-#include <QtCore/qglobal.h>
-#include <new>
+#include <QtCore/qvarlengtharray.h>
QT_BEGIN_HEADER
@@ -63,87 +61,29 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Core)
-template<class T, int Prealloc>
-class QPodList
+template <typename T, int Prealloc>
+class QPodList : public QVarLengthArray<T, Prealloc>
{
+ using QVarLengthArray<T, Prealloc>::s;
+ using QVarLengthArray<T, Prealloc>::a;
+ using QVarLengthArray<T, Prealloc>::ptr;
+ using QVarLengthArray<T, Prealloc>::realloc;
public:
- inline explicit QPodList(int size = 0);
+ inline explicit QPodList(int size = 0)
+ : QVarLengthArray<T, Prealloc>(size)
+ {}
- inline QPodList(const QPodList<T, Prealloc> &other)
- : a(Prealloc), s(0), ptr(reinterpret_cast<T *>(array))
+ inline void insert(int idx, const T &t)
{
- append(other.constData(), other.size());
- }
-
- inline ~QPodList() {
- if (ptr != reinterpret_cast<T *>(array))
- qFree(ptr);
- }
- inline QPodList<T, Prealloc> &operator=(const QPodList<T, Prealloc> &other)
- {
- if (this != &other) {
- clear();
- append(other.constData(), other.size());
- }
- return *this;
- }
-
- inline int size() const { return s; }
- inline int count() const { return s; }
- inline bool isEmpty() const { return (s == 0); }
- inline void resize(int size);
- inline void clear() { resize(0); }
-
- inline int capacity() const { return a; }
- inline void reserve(int size);
-
- inline T &operator[](int idx) {
- Q_ASSERT(idx >= 0 && idx < s);
- return ptr[idx];
- }
- inline const T &operator[](int idx) const {
- Q_ASSERT(idx >= 0 && idx < s);
- return ptr[idx];
- }
-
- inline const T &at(int idx) const {
- Q_ASSERT(idx >= 0 && idx < s);
- return ptr[idx];
- }
-
- inline const T &first() const {
- return at(0);
- }
-
- inline T& append() {
- const int idx = s++;
- if (s == a)
- realloc(s, s<<1);
- return ptr[idx];
- }
- inline void append(const T &t) {
- append() = t;
- }
-
- inline T& insert(int idx) {
- Q_ASSERT(idx >= 0 && idx <= s);
const int sz = s++;
if (s == a)
- realloc(s, s<<1);
+ realloc(s, s << 1);
::memmove(ptr + idx + 1, ptr + idx, (sz - idx) * sizeof(T));
- return ptr[idx];
- }
- inline void insert(int idx, const T &t) {
- insert(idx) = t;
+ ptr[idx] = t;
}
- inline void removeAt(int idx) {
- Q_ASSERT(idx >= 0 && idx < s);
- ::memmove(ptr + idx, ptr + idx + 1, (s - idx - 1) * sizeof(T));
- --s;
- }
-
- inline void removeAll(const T &t) {
+ inline void removeAll(const T &t)
+ {
int i = 0;
for (int j = 0; j < s; ++j) {
if (ptr[j] != t)
@@ -152,110 +92,22 @@ public:
s = i;
}
- inline int indexOf(const T &t, int from = 0) const {
- if (from < 0)
- from = qMax(from + s, 0);
- if (from < s) {
- const T *n = ptr + from - 1;
- const T *e = ptr + s;
- while (++n != e)
- if (*n == t)
- return n - ptr;
- }
- return -1;
- }
-
- inline bool contains(const T &t) const {
- return indexOf(t) >= 0;
+ inline void removeAt(int idx)
+ {
+ Q_ASSERT(idx >= 0 && idx < s);
+ ::memmove(ptr + idx, ptr + idx + 1, (s - idx - 1) * sizeof(T));
+ --s;
}
- inline T takeFirst() {
+ inline T takeFirst()
+ {
Q_ASSERT(s > 0);
T tmp = ptr[0];
removeAt(0);
return tmp;
}
-
- inline T *data() { return ptr; }
- inline const T *data() const { return ptr; }
- inline const T * constData() const { return ptr; }
-
-private:
- void append(const T *buf, int size);
- void realloc(int size, int alloc);
-
- int a;
- int s;
- T *ptr;
- union {
- // ### Qt 5: Use 'Prealloc * sizeof(T)' as array size
- char array[sizeof(qint64) * (((Prealloc * sizeof(T)) / sizeof(qint64)) + 1)];
- qint64 q_for_alignment_1;
- double q_for_alignment_2;
- };
};
-template <class T, int Prealloc>
-Q_INLINE_TEMPLATE QPodList<T, Prealloc>::QPodList(int asize)
- : s(asize) {
- if (s > Prealloc) {
- ptr = reinterpret_cast<T *>(qMalloc(s * sizeof(T)));
- a = s;
- } else {
- ptr = reinterpret_cast<T *>(array);
- a = Prealloc;
- }
-}
-
-template <class T, int Prealloc>
-Q_INLINE_TEMPLATE void QPodList<T, Prealloc>::resize(int asize)
-{ realloc(asize, qMax(asize, a)); }
-
-template <class T, int Prealloc>
-Q_INLINE_TEMPLATE void QPodList<T, Prealloc>::reserve(int asize)
-{ if (asize > a) realloc(s, asize); }
-
-template <class T, int Prealloc>
-Q_OUTOFLINE_TEMPLATE void QPodList<T, Prealloc>::append(const T *abuf, int asize)
-{
- Q_ASSERT(abuf);
- if (asize <= 0)
- return;
-
- const int idx = s;
- const int news = s + asize;
- if (news >= a)
- realloc(news, news<<1);
- else
- s = news;
-
- qMemCopy(&ptr[idx], abuf, asize * sizeof(T));
-}
-
-template <class T, int Prealloc>
-Q_OUTOFLINE_TEMPLATE void QPodList<T, Prealloc>::realloc(int asize, int aalloc)
-{
- Q_ASSERT(aalloc >= asize);
- T *oldPtr = ptr;
- int osize = s;
- s = asize;
-
- if (aalloc != a) {
- ptr = reinterpret_cast<T *>(qMalloc(aalloc * sizeof(T)));
- if (ptr) {
- a = aalloc;
- qMemCopy(ptr, oldPtr, osize * sizeof(T));
- } else {
- ptr = oldPtr;
- s = 0;
- asize = 0;
- }
- }
-
- if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
- qFree(oldPtr);
-}
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp
index e1c3921..f357956 100644
--- a/src/corelib/tools/qregexp.cpp
+++ b/src/corelib/tools/qregexp.cpp
@@ -1297,14 +1297,20 @@ void QRegExpMatchState::prepareForMatch(QRegExpEngine *eng)
int ns = eng->s.size(); // number of states
int ncap = eng->ncap;
#ifndef QT_NO_REGEXP_OPTIM
- slideTabSize = qMax(eng->minl + 1, 16);
+ int newSlideTabSize = qMax(eng->minl + 1, 16);
#else
- slideTabSize = 0;
+ int newSlideTabSize = 0;
#endif
int numCaptures = eng->numCaptures();
- capturedSize = 2 + 2 * numCaptures;
- bigArray = (int *)realloc(bigArray, ((3 + 4 * ncap) * ns + 4 * ncap + slideTabSize + capturedSize)*sizeof(int));
+ int newCapturedSize = 2 + 2 * numCaptures;
+ bigArray = (int *)realloc(bigArray, ((3 + 4 * ncap) * ns + 4 * ncap + newSlideTabSize + newCapturedSize)*sizeof(int));
+ Q_CHECK_PTR(bigArray);
+ // set all internal variables only _after_ bigArray is realloc'ed
+ // to prevent a broken regexp in oom case
+
+ slideTabSize = newSlideTabSize;
+ capturedSize = newCapturedSize;
inNextStack = bigArray;
memset(inNextStack, -1, ns * sizeof(int));
curStack = inNextStack + ns;
@@ -3281,10 +3287,15 @@ static void derefEngine(QRegExpEngine *eng, const QRegExpEngineKey &key)
#if !defined(QT_NO_REGEXP_OPTIM)
if (globalEngineCache()) {
QMutexLocker locker(mutex());
- globalEngineCache()->insert(key, eng, 4 + key.pattern.length() / 4);
- }
- else
+ QT_TRY {
+ globalEngineCache()->insert(key, eng, 4 + key.pattern.length() / 4);
+ } QT_CATCH(const std::bad_alloc &) {
+ // in case of an exception (e.g. oom), just delete the engine
+ delete eng;
+ }
+ } else {
delete eng;
+ }
#else
Q_UNUSED(key);
delete eng;
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index 3a0901d..ac33353 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -199,9 +199,8 @@ public:
inline void clear() {
if(!buffers.isEmpty()) {
- QByteArray tmp = buffers[0];
- buffers.clear();
- buffers << tmp;
+ // remove all but the first
+ buffers.erase(buffers.begin() + 1, buffers.end());
if (buffers.at(0).size() != basicBlockSize)
buffers[0].resize(basicBlockSize);
}
diff --git a/src/corelib/tools/qscopedpointer.cpp b/src/corelib/tools/qscopedpointer.cpp
new file mode 100644
index 0000000..8150a18
--- /dev/null
+++ b/src/corelib/tools/qscopedpointer.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QScopedPointer
+ \brief The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon destruction.
+ \since 4.6
+ \reentrant
+ \ingroup misc
+
+ Managing heap allocated objects manually is hard and error prone, with the
+ common result that code leaks memory and is hard to maintain.
+ QScopedPointer is a small utility class that heavily simplifies this by
+ assigning stack-based memory ownership to heap allocations, more generally
+ called resource acquisition is initialization(RAII).
+
+ QScopedPointer guarantees that the object pointed to will get deleted when
+ the current scope dissapears, and it also has no way of releasing
+ ownership, hence clearly communicating the lifetime and ownership of the
+ object. These guarantees are convenient when reading the code.
+
+ Consider this function which does heap allocations, and have various exit points:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 0
+
+ It's encumbered by the manual delete calls. With QScopedPointer, the code
+ can be simplified to:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 1
+
+ The code the compiler generates for QScopedPointer is the same as when
+ writing it manually. Code that makes use of \a delete are candidates for
+ QScopedPointer usage(and if not, possibly another type of smart pointer
+ such as QSharedPointer). QScopedPointer intentionally has no copy
+ constructor or assignment operator, such that ownership and lifetime is
+ clearly communicated.
+
+ The const qualification on a regular C++ pointer can also be expressed with
+ a QScopedPointer:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 2
+
+ \note QScopedPointer does not work with arrays.
+
+ \sa QSharedPointer
+*/
+
+/*!
+ \fn QScopedPointer::QScopedPointer(T *p = 0)
+
+ Constructs this QScopedPointer instance and sets its pointer to \a p.
+*/
+
+/*!
+ \fn QScopedPointer::~QScopedPointer()
+
+ Destroys this QScopedPointer object. Delete the object its pointer points
+ to.
+*/
+
+/*!
+ \fn T *QScopedPointer::data() const
+
+ Returns the value of the pointer referenced by this object. QScopedPointer
+ still owns the object pointed to.
+*/
+
+/*!
+ \fn T &QScopedPointer::operator*() const
+
+ Provides access to the scoped pointer's object.
+
+ If the contained pointer is \c null, behavior is undefined.
+ \sa isNull()
+*/
+
+/*!
+ \fn T *QScopedPointer::operator->() const
+
+ Provides access to the scoped pointer's object.
+
+ If the contained pointer is \c null, behavior is undefined.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QScopedPointer::operator bool() const
+
+ Returns \c true if this object is not \c null. This function is suitable
+ for use in \tt if-constructs, like:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 3
+
+ \sa isNull()
+*/
+
+/*!
+ \fn bool QScopedPointer::isNull() const
+
+ Returns \c true if this object is holding a pointer that is \c null.
+*/
+
+/*!
+ \fn void QScopedPointer::reset(T *other = 0)
+
+ Deletes the existing object its pointing to if any, and sets its pointer to
+ \a other. QScopedPointer now owns \a other and will delete it in its
+ destructor.
+
+ If \a other is equal to the value returned by data(), behavior is
+ undefined.
+*/
+
+/*!
+ \fn T *QScopedPointer::take()
+
+ Returns the value of the pointer referenced by this object. The pointer of this
+ QScopedPointer object will be reset to \c null.
+*/
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/tools/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h
new file mode 100644
index 0000000..fc8f9e2
--- /dev/null
+++ b/src/corelib/tools/qscopedpointer.h
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCOPEDPOINTER_H
+#define QSCOPEDPOINTER_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+QT_MODULE(Core)
+
+template <typename T>
+class QScopedPointer
+{
+public:
+ explicit inline QScopedPointer(T *p = 0) : d(p)
+ {
+ }
+
+ inline ~QScopedPointer()
+ {
+ delete d;
+ }
+
+ inline T &operator*() const
+ {
+ return *d;
+ }
+
+ inline T *operator->() const
+ {
+ return d;
+ }
+
+ inline bool operator==(const QScopedPointer<T> &other) const
+ {
+ return d == other.d;
+ }
+
+ inline bool operator!=(const QScopedPointer<T> &other) const
+ {
+ return d != other.d;
+ }
+
+ inline operator bool() const
+ {
+ return d;
+ }
+
+ inline T *data() const
+ {
+ return d;
+ }
+
+ inline bool isNull() const
+ {
+ return !d;
+ }
+
+ inline void reset(T *other = 0)
+ {
+ T *oldD = d;
+ d = other;
+ delete oldD;
+ }
+
+ inline T *take()
+ {
+ T *oldD = d;
+ d = 0;
+ return oldD;
+ }
+
+protected:
+ T *d;
+
+private:
+ Q_DISABLE_COPY(QScopedPointer)
+};
+
+/* internal class - allows special handling for resetting and cleaning the pointer */
+template <typename T, typename CustomHandler>
+class QScopedCustomPointer : public QScopedPointer<T>
+{
+public:
+ inline QScopedCustomPointer(T *p = 0)
+ : QScopedPointer<T>(p)
+ {
+ }
+
+ inline ~QScopedCustomPointer()
+ {
+ T *oldD = this->d;
+ this->d = 0;
+ CustomHandler::cleanup(oldD);
+ }
+
+ inline void reset(T *other = 0)
+ {
+ CustomHandler::reset(this->d, other);
+ }
+
+ inline T *&data_ptr()
+ {
+ return this->d;
+ }
+};
+
+/* Internal helper class - a handler for QShared* classes, to be used in QScopedCustomPointer */
+template <typename T>
+class QScopedSharedPointerHandler
+{
+public:
+ static inline void cleanup(T *d)
+ {
+ if (d && !d->ref.deref())
+ delete d;
+ }
+
+ static inline void reset(T *&d, T *other)
+ {
+ T *oldD = d;
+ d = other;
+ cleanup(oldD);
+ }
+};
+
+/* Internal. This should really have been a typedef, but you can't have a templated typedef :)
+ This class is basically a scoped pointer pointing to a ref-counted object
+ */
+template <typename T>
+class QScopedSharedPointer : public QScopedCustomPointer<T, QScopedSharedPointerHandler<T> >
+{
+public:
+ inline QScopedSharedPointer(T *p = 0)
+ : QScopedCustomPointer<T, QScopedSharedPointerHandler<T> >(p)
+ {
+ }
+
+ inline void detach()
+ {
+ qAtomicDetach(this->d);
+ }
+
+ inline void assign(T *other)
+ {
+ if (this->d == other)
+ return;
+ if (other)
+ other->ref.ref();
+ T *oldD = this->d;
+ this->d = other;
+ QScopedSharedPointerHandler<T>::cleanup(oldD);
+ }
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QSCOPEDPOINTER_H
diff --git a/src/corelib/tools/qshareddata.cpp b/src/corelib/tools/qshareddata.cpp
index 2b879ea..03bc964 100644
--- a/src/corelib/tools/qshareddata.cpp
+++ b/src/corelib/tools/qshareddata.cpp
@@ -231,7 +231,7 @@ QT_BEGIN_NAMESPACE
In the member function documentation, \e{d pointer} always refers
to the internal pointer to the shared data object.
- \sa QSharedData, QExplicitlySharedDataPointer
+ \sa QSharedData, QExplicitlySharedDataPointer, QScopedPointer, QSharedPointer
*/
/*! \fn T& QSharedDataPointer::operator*()
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index c3a989e..dee06f0 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -102,13 +102,18 @@
except that it only detaches if
QExplicitlySharedDataPointer::detach() is explicitly called.
+ QScopedPointer simply holds a pointer to a heap allocated object and
+ deletes it in its destructor. This class is useful when an object needs to
+ be heap allocated and deleted, but no more. QScopedPointer is lightweight,
+ it makes no use of additional structure or reference counting.
+
Finally, QPointer holds a pointer to a QObject-derived object, but
it does so weakly. QPointer is similar, in that behaviour, to
QWeakPointer: it does not allow you to prevent the object from
being destroyed. All you can do is query whether it has been
destroyed or not.
- \sa QSharedDataPointer, QWeakPointer
+ \sa QSharedDataPointer, QWeakPointer, QScopedPointer
*/
/*!
@@ -130,7 +135,7 @@
must first create a QSharedPointer object and verify if the pointer
is null or not.
- \sa QSharedPointer
+ \sa QSharedPointer, QScopedPointer
*/
/*!
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index c3649e3..e61a568 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -846,6 +846,7 @@ QString::QString(const QChar *unicode, int size)
d->ref.ref();
} else {
d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ Q_CHECK_PTR(d);
d->ref = 1;
d->alloc = d->size = size;
d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
@@ -869,6 +870,7 @@ QString::QString(int size, QChar ch)
d->ref.ref();
} else {
d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ Q_CHECK_PTR(d);
d->ref = 1;
d->alloc = d->size = size;
d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
@@ -894,7 +896,9 @@ QString::QString(int size, QChar ch)
*/
QString::QString(QChar ch)
{
- d = (Data *)qMalloc(sizeof(Data) + sizeof(QChar));
+ void *buf = qMalloc(sizeof(Data) + sizeof(QChar));
+ Q_CHECK_PTR(buf);
+ d = reinterpret_cast<Data *>(buf);
d->ref = 1;
d->alloc = d->size = 1;
d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
@@ -1064,8 +1068,7 @@ void QString::realloc(int alloc)
{
if (d->ref != 1 || d->data != d->array) {
Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc * sizeof(QChar)));
- if (!x)
- return;
+ Q_CHECK_PTR(x);
x->size = qMin(alloc, d->size);
::memcpy(x->array, d->data, x->size * sizeof(QChar));
x->array[x->size] = 0;
@@ -1088,8 +1091,7 @@ void QString::realloc(int alloc)
}
#endif
Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar)));
- if (!x)
- return;
+ Q_CHECK_PTR(x);
x->alloc = alloc;
x->data = x->array;
d = x;
@@ -1246,6 +1248,7 @@ QString& QString::insert(int i, const QChar *unicode, int size)
if (s >= d->data && s < d->data + d->alloc) {
// Part of me - take a copy
ushort *tmp = static_cast<ushort *>(qMalloc(size * sizeof(QChar)));
+ Q_CHECK_PTR(tmp);
memcpy(tmp, s, size * sizeof(QChar));
insert(i, reinterpret_cast<const QChar *>(tmp), size);
qFree(tmp);
@@ -1600,51 +1603,69 @@ QString &QString::replace(const QString &before, const QString &after, Qt::CaseS
*/
void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen)
{
- if (blen == alen) {
- detach();
- for (int i = 0; i < nIndices; ++i)
- memcpy(d->data + indices[i], after, alen * sizeof(QChar));
- } else if (alen < blen) {
+ // copy *after in case it lies inside our own d->data area
+ // (which we could possibly invalidate via a realloc or corrupt via memcpy operations.)
+ QChar *afterBuffer = const_cast<QChar *>(after);
+ if (after >= reinterpret_cast<QChar *>(d->data) && after < reinterpret_cast<QChar *>(d->data) + d->size) {
+ afterBuffer = static_cast<QChar *>(qMalloc(alen*sizeof(QChar)));
+ Q_CHECK_PTR(afterBuffer);
+ ::memcpy(afterBuffer, after, alen*sizeof(QChar));
+ }
+
+ QT_TRY {
detach();
- uint to = indices[0];
- if (alen)
- memcpy(d->data+to, after, alen*sizeof(QChar));
- to += alen;
- uint movestart = indices[0] + blen;
- for (int i = 1; i < nIndices; ++i) {
- int msize = indices[i] - movestart;
- if (msize > 0) {
- memmove(d->data + to, d->data + movestart, msize * sizeof(QChar));
- to += msize;
+ if (blen == alen) {
+ // replace in place
+ for (int i = 0; i < nIndices; ++i)
+ memcpy(d->data + indices[i], afterBuffer, alen * sizeof(QChar));
+ } else if (alen < blen) {
+ // replace from front
+ uint to = indices[0];
+ if (alen)
+ memcpy(d->data+to, after, alen*sizeof(QChar));
+ to += alen;
+ uint movestart = indices[0] + blen;
+ for (int i = 1; i < nIndices; ++i) {
+ int msize = indices[i] - movestart;
+ if (msize > 0) {
+ memmove(d->data + to, d->data + movestart, msize * sizeof(QChar));
+ to += msize;
+ }
+ if (alen) {
+ memcpy(d->data + to, afterBuffer, alen*sizeof(QChar));
+ to += alen;
+ }
+ movestart = indices[i] + blen;
}
- if (alen) {
- memcpy(d->data + to, after, alen*sizeof(QChar));
- to += alen;
+ int msize = d->size - movestart;
+ if (msize > 0)
+ memmove(d->data + to, d->data + movestart, msize * sizeof(QChar));
+ resize(d->size - nIndices*(blen-alen));
+ } else {
+ // replace from back
+ int adjust = nIndices*(alen-blen);
+ int newLen = d->size + adjust;
+ int moveend = d->size;
+ resize(newLen);
+
+ while (nIndices) {
+ --nIndices;
+ int movestart = indices[nIndices] + blen;
+ int insertstart = indices[nIndices] + nIndices*(alen-blen);
+ int moveto = insertstart + alen;
+ memmove(d->data + moveto, d->data + movestart,
+ (moveend - movestart)*sizeof(QChar));
+ memcpy(d->data + insertstart, afterBuffer, alen*sizeof(QChar));
+ moveend = movestart-blen;
}
- movestart = indices[i] + blen;
- }
- int msize = d->size - movestart;
- if (msize > 0)
- memmove(d->data + to, d->data + movestart, msize * sizeof(QChar));
- resize(d->size - nIndices*(blen-alen));
- } else {
- // we have a table of replacement positions, use them for fast replacing
- int adjust = nIndices*(alen-blen);
- int newLen = d->size + adjust;
- int moveend = d->size;
- resize(newLen);
-
- while (nIndices) {
- --nIndices;
- int movestart = indices[nIndices] + blen;
- int insertstart = indices[nIndices] + nIndices*(alen-blen);
- int moveto = insertstart + alen;
- memmove(d->data + moveto, d->data + movestart,
- (moveend - movestart)*sizeof(QChar));
- memcpy(d->data + insertstart, after, alen*sizeof(QChar));
- moveend = movestart-blen;
}
+ } QT_CATCH(const std::bad_alloc &) {
+ if (afterBuffer != after)
+ qFree(afterBuffer);
+ QT_RETHROW;
}
+ if (afterBuffer != after)
+ qFree(afterBuffer);
}
/*!
@@ -1672,21 +1693,7 @@ QString &QString::replace(const QChar *before, int blen,
if (alen == 0 && blen == 0)
return *this;
- // protect against before or after being part of this
- const QChar *a = after;
- const QChar *b = before;
- if (after >= (const QChar *)d->data && after < (const QChar *)d->data + d->size) {
- QChar *copy = (QChar *)malloc(alen*sizeof(QChar));
- memcpy(copy, after, alen*sizeof(QChar));
- a = copy;
- }
- if (before >= (const QChar *)d->data && before < (const QChar *)d->data + d->size) {
- QChar *copy = (QChar *)malloc(blen*sizeof(QChar));
- memcpy(copy, before, blen*sizeof(QChar));
- b = copy;
- }
-
- QStringMatcher matcher(b, blen, cs);
+ QStringMatcher matcher(before, blen, cs);
int index = 0;
while (1) {
@@ -1705,7 +1712,7 @@ QString &QString::replace(const QChar *before, int blen,
if (!pos)
break;
- replace_helper(indices, pos, blen, a, alen);
+ replace_helper(indices, pos, blen, after, alen);
if (index == -1)
break;
@@ -1713,11 +1720,6 @@ QString &QString::replace(const QChar *before, int blen,
index += pos*(alen-blen);
}
- if (a != after)
- ::free((QChar *)a);
- if (b != before)
- ::free((QChar *)b);
-
return *this;
}
@@ -3450,6 +3452,7 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size)
if (size < 0)
size = qstrlen(str);
d = static_cast<Data *>(qMalloc(sizeof(Data) + size * sizeof(QChar)));
+ Q_CHECK_PTR(d);
d->ref = 1;
d->alloc = d->size = size;
d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
@@ -3457,7 +3460,7 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size)
ushort *i = d->data;
d->array[size] = '\0';
while (size--)
- *i++ = (uchar)*str++;
+ *i++ = (uchar)*str++;
}
return d;
}
@@ -6867,6 +6870,7 @@ void QString::updateProperties() const
QString QString::fromRawData(const QChar *unicode, int size)
{
Data *x = static_cast<Data *>(qMalloc(sizeof(Data)));
+ Q_CHECK_PTR(x);
if (unicode) {
x->data = (ushort *)unicode;
} else {
diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/tools/qtextboundaryfinder.cpp
index 8a8e95b..5ca6a11 100644
--- a/src/corelib/tools/qtextboundaryfinder.cpp
+++ b/src/corelib/tools/qtextboundaryfinder.cpp
@@ -176,6 +176,7 @@ QTextBoundaryFinder::QTextBoundaryFinder(const QTextBoundaryFinder &other)
, freePrivate(true)
{
d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes));
+ Q_CHECK_PTR(d);
memcpy(d, other.d, length*sizeof(HB_CharAttributes));
}
@@ -193,8 +194,11 @@ QTextBoundaryFinder &QTextBoundaryFinder::operator=(const QTextBoundaryFinder &o
length = other.length;
pos = other.pos;
freePrivate = true;
-
- d = (QTextBoundaryFinderPrivate *) realloc(d, length*sizeof(HB_CharAttributes));
+
+ QTextBoundaryFinderPrivate *newD = (QTextBoundaryFinderPrivate *)
+ realloc(d, length*sizeof(HB_CharAttributes));
+ Q_CHECK_PTR(newD);
+ d = newD;
memcpy(d, other.d, length*sizeof(HB_CharAttributes));
return *this;
@@ -221,6 +225,7 @@ QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, const QString &strin
, freePrivate(true)
{
d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes));
+ Q_CHECK_PTR(d);
init(t, chars, length, d->attributes);
}
@@ -248,6 +253,7 @@ QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, const QChar *chars,
freePrivate = false;
} else {
d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes));
+ Q_CHECK_PTR(d);
freePrivate = true;
}
init(t, chars, length, d->attributes);
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index e2f60ed..b41240e 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -52,6 +52,9 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Core)
+template<class T, int Prealloc>
+class QPodList;
+
// Prealloc = 256 by default, specified in qcontainerfwd.h
template<class T, int Prealloc>
class QVarLengthArray
@@ -122,6 +125,7 @@ public:
inline const T * constData() const { return ptr; }
private:
+ friend class QPodList<T, Prealloc>;
void realloc(int size, int alloc);
int a;
@@ -140,6 +144,7 @@ Q_INLINE_TEMPLATE QVarLengthArray<T, Prealloc>::QVarLengthArray(int asize)
: s(asize) {
if (s > Prealloc) {
ptr = reinterpret_cast<T *>(qMalloc(s * sizeof(T)));
+ Q_CHECK_PTR(ptr);
a = s;
} else {
ptr = reinterpret_cast<T *>(array);
@@ -161,25 +166,24 @@ Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reserve(int asize)
{ if (asize > a) realloc(s, asize); }
template <class T, int Prealloc>
-Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::append(const T *abuf, int asize)
+Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::append(const T *abuf, int increment)
{
Q_ASSERT(abuf);
- if (asize <= 0)
+ if (increment <= 0)
return;
- const int idx = s;
- const int news = s + asize;
- if (news >= a)
- realloc(s, qMax(s<<1, news));
- s = news;
+ const int asize = s + increment;
+
+ if (asize >= a)
+ realloc(s, qMax(s*2, asize));
if (QTypeInfo<T>::isComplex) {
- T *i = ptr + idx;
- T *j = i + asize;
- while (i < j)
- new (i++) T(*abuf++);
+ // call constructor for new objects (which can throw)
+ while (s < asize)
+ new (ptr+(s++)) T(*abuf++);
} else {
- qMemCopy(&ptr[idx], abuf, asize * sizeof(T));
+ qMemCopy(&ptr[s], abuf, increment * sizeof(T));
+ s = asize;
}
}
@@ -189,46 +193,58 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::realloc(int asize, int a
Q_ASSERT(aalloc >= asize);
T *oldPtr = ptr;
int osize = s;
- s = asize;
+ // s = asize;
if (aalloc != a) {
ptr = reinterpret_cast<T *>(qMalloc(aalloc * sizeof(T)));
+ Q_CHECK_PTR(ptr);
if (ptr) {
+ s = 0;
a = aalloc;
if (QTypeInfo<T>::isStatic) {
- T *i = ptr + osize;
- T *j = oldPtr + osize;
- while (i != ptr) {
- new (--i) T(*--j);
- j->~T();
+ QT_TRY {
+ while (s < asize) {
+ new (ptr+s) T(*(oldPtr+s));
+ (oldPtr+s)->~T();
+ s++;
+ }
+ } QT_CATCH(...) {
+ // clean up all the old objects and then free the old ptr
+ int sClean = s;
+ while (sClean < osize)
+ (oldPtr+(sClean++))->~T();
+ if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
+ qFree(oldPtr);
+ QT_RETHROW;
}
} else {
- qMemCopy(ptr, oldPtr, osize * sizeof(T));
+ qMemCopy(ptr, oldPtr, qMin(asize, osize) * sizeof(T));
+ s = asize;
}
} else {
ptr = oldPtr;
- s = 0;
- asize = 0;
+ return;
}
}
if (QTypeInfo<T>::isComplex) {
- if (asize < osize) {
- T *i = oldPtr + osize;
- T *j = oldPtr + asize;
- while (i-- != j)
- i->~T();
- } else {
- T *i = ptr + asize;
- T *j = ptr + osize;
- while (i != j)
- new (--i) T;
- }
+ while (osize > asize)
+ (oldPtr+(--osize))->~T();
+ if( oldPtr == ptr )
+ s = osize;
}
if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
qFree(oldPtr);
+
+ if (QTypeInfo<T>::isComplex) {
+ // call default constructor for new objects (which can throw)
+ while (s < asize)
+ new (ptr+(s++)) T;
+ } else {
+ s = asize;
+ }
}
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp
index 6b26b2e..04e9ace 100644
--- a/src/corelib/tools/qvector.cpp
+++ b/src/corelib/tools/qvector.cpp
@@ -50,6 +50,7 @@ QVectorData QVectorData::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, tr
QVectorData *QVectorData::malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init)
{
QVectorData* p = (QVectorData *)qMalloc(sizeofTypedData + (size - 1) * sizeofT);
+ Q_CHECK_PTR(p);
::memcpy(p, init, sizeofTypedData + (qMin(size, init->alloc) - 1) * sizeofT);
return p;
}
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 1f047b8..610b8e7 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -77,6 +77,7 @@ struct Q_CORE_EXPORT QVectorData
static QVectorData shared_null;
// ### Qt 5: rename to 'allocate()'. The current name causes problems for
// some debugges when the QVector is member of a class within an unnamed namespace.
+ // ### Qt 5: can be removed completely. (Ralf)
static QVectorData *malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init);
static int grow(int sizeofTypedData, int size, int sizeofT, bool excessive);
};
@@ -379,7 +380,9 @@ QVector<T> &QVector<T>::operator=(const QVector<T> &v)
template <typename T>
inline QVectorData *QVector<T>::malloc(int aalloc)
{
- return static_cast<QVectorData *>(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T)));
+ QVectorData *data = static_cast<QVectorData *>(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T)));
+ Q_CHECK_PTR(data);
+ return data;
}
template <typename T>
@@ -428,74 +431,79 @@ void QVector<T>::free(Data *x)
template <typename T>
void QVector<T>::realloc(int asize, int aalloc)
{
- T *j, *i, *b;
+ T *pOld;
+ T *pNew;
union { QVectorData *p; Data *d; } x;
x.d = d;
- if (QTypeInfo<T>::isComplex && aalloc == d->alloc && d->ref == 1) {
- // pure resize
- i = d->array + d->size;
- j = d->array + asize;
- if (i > j) {
- while (i-- != j)
- i->~T();
- } else {
- while (j-- != i)
- new (j) T;
+ if (QTypeInfo<T>::isComplex && asize < d->size && d->ref == 1 ) {
+ // call the destructor on all objects that need to be
+ // destroyed when shrinking
+ pOld = d->array + d->size;
+ pNew = d->array + asize;
+ while (asize < d->size) {
+ (--pOld)->~T();
+ d->size--;
}
- d->size = asize;
- return;
}
if (aalloc != d->alloc || d->ref != 1) {
// (re)allocate memory
if (QTypeInfo<T>::isStatic) {
x.p = malloc(aalloc);
+ Q_CHECK_PTR(x.p);
+ x.d->size = 0;
} else if (d->ref != 1) {
- x.p = QVectorData::malloc(sizeOfTypedData(), aalloc, sizeof(T), p);
- } else {
+ x.p = malloc(aalloc);
+ Q_CHECK_PTR(x.p);
if (QTypeInfo<T>::isComplex) {
- // call the destructor on all objects that need to be
- // destroyed when shrinking
- if (asize < d->size) {
- j = d->array + asize;
- i = d->array + d->size;
- while (i-- != j)
- i->~T();
- i = d->array + asize;
- }
+ x.d->size = 0;
+ } else {
+ ::memcpy(x.p, p, sizeOfTypedData() + (qMin(aalloc, p->alloc) - 1) * sizeof(T));
+ x.d->size = d->size;
+ }
+ } else {
+ QT_TRY {
+ QVectorData *mem = static_cast<QVectorData *>(qRealloc(p, sizeOfTypedData() + (aalloc - 1) * sizeof(T)));
+ Q_CHECK_PTR(mem);
+ x.p = p = mem;
+ x.d->size = d->size;
+ } QT_CATCH (const std::bad_alloc &) {
+ if (aalloc > d->alloc) // ignore the error in case we are just shrinking.
+ QT_RETHROW;
}
- x.p = p = static_cast<QVectorData *>(qRealloc(p, sizeOfTypedData() + (aalloc - 1) * sizeof(T)));
}
x.d->ref = 1;
+ x.d->alloc = aalloc;
x.d->sharable = true;
x.d->capacity = d->capacity;
-
}
+
if (QTypeInfo<T>::isComplex) {
- if (asize < d->size) {
- j = d->array + asize;
- i = x.d->array + asize;
- } else {
- // construct all new objects when growing
- i = x.d->array + asize;
- j = x.d->array + d->size;
- while (i != j)
- new (--i) T;
- j = d->array + d->size;
- }
- if (i != j) {
+ QT_TRY {
+ pOld = d->array + x.d->size;
+ pNew = x.d->array + x.d->size;
// copy objects from the old array into the new array
- b = x.d->array;
- while (i != b)
- new (--i) T(*--j);
+ while (x.d->size < qMin(asize, d->size)) {
+ new (pNew++) T(*pOld++);
+ x.d->size++;
+ }
+ // construct all new objects when growing
+ while (x.d->size < asize) {
+ new (pNew++) T;
+ x.d->size++;
+ }
+ } QT_CATCH (...) {
+ free(x.d);
+ QT_RETHROW;
}
- } else if (asize > d->size) {
+
+ } else if (asize > x.d->size) {
// initialize newly allocated memory to 0
- qMemSet(x.d->array + d->size, 0, (asize - d->size) * sizeof(T));
+ qMemSet(x.d->array + x.d->size, 0, (asize - x.d->size) * sizeof(T));
}
x.d->size = asize;
- x.d->alloc = aalloc;
+
if (d != x.d) {
if (!d->ref.deref())
free(d);
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index c2381ce..8d27100 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -36,7 +36,8 @@ HEADERS += \
tools/qtimeline.h \
tools/qunicodetables_p.h \
tools/qvarlengtharray.h \
- tools/qvector.h
+ tools/qvector.h \
+ tools/qscopedpointer.h
SOURCES += \
diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp
index ff1a01f..6fe6ebf 100644
--- a/src/corelib/xml/qxmlstream.cpp
+++ b/src/corelib/xml/qxmlstream.cpp
@@ -429,7 +429,6 @@ QXmlStreamReader::~QXmlStreamReader()
Q_D(QXmlStreamReader);
if (d->deleteDevice)
delete d->device;
- delete d;
}
/*! \fn bool QXmlStreamReader::hasError() const
@@ -819,7 +818,9 @@ inline void QXmlStreamReaderPrivate::reallocateStack()
{
stack_size <<= 1;
sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value)));
+ Q_CHECK_PTR(sym_stack);
state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
+ Q_CHECK_PTR(sym_stack);
}
@@ -3131,8 +3132,6 @@ QXmlStreamWriter::QXmlStreamWriter(QString *string)
*/
QXmlStreamWriter::~QXmlStreamWriter()
{
- Q_D(QXmlStreamWriter);
- delete d;
}
diff --git a/src/corelib/xml/qxmlstream.h b/src/corelib/xml/qxmlstream.h
index 2ba7972..6903d56 100644
--- a/src/corelib/xml/qxmlstream.h
+++ b/src/corelib/xml/qxmlstream.h
@@ -48,6 +48,7 @@
#include <QtCore/QString>
#include <QtCore/QVector>
+#include <QtCore/QScopedPointer>
QT_BEGIN_HEADER
@@ -392,7 +393,7 @@ public:
private:
Q_DISABLE_COPY(QXmlStreamReader)
Q_DECLARE_PRIVATE(QXmlStreamReader)
- QXmlStreamReaderPrivate *d_ptr;
+ QScopedPointer<QXmlStreamReaderPrivate> d_ptr;
};
#endif // QT_NO_XMLSTREAMREADER
@@ -465,7 +466,7 @@ public:
private:
Q_DISABLE_COPY(QXmlStreamWriter)
Q_DECLARE_PRIVATE(QXmlStreamWriter)
- QXmlStreamWriterPrivate *d_ptr;
+ QScopedPointer<QXmlStreamWriterPrivate> d_ptr;
};
#endif // QT_NO_XMLSTREAMWRITER