PDA

View Full Version : Memory leak



yxtx1984
25th February 2010, 10:28
I declare a global class variable, and it inherit from QObject, the constructor is like this:

MyClass a;

MyClass::MyClass(QObject *parent)
: QObject(parent)
{

}

The default parent is NULL, so when it's create the parent is set to NULL.
The problem is that it will raise memory problem.
Before a is created, it will call QObject's constructor, this is the constructor in the source code QObject.cpp.

QObject::QObject(QObject *parent)
: d_ptr(new QObjectPrivate)
{
Q_D(QObject);
d_ptr->q_ptr = this;
d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
d->threadData->ref();
QT_TRY {
if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
parent = 0;
setParent(parent);
} QT_CATCH(...) {
d->threadData->deref();
QT_RETHROW;
}
qt_addObject(this);
}

QThreadData *QThreadData::current()
{
qt_create_tls();
QThreadData *threadData = reinterpret_cast<QThreadData *>(TlsGetValue(qt_current_thread_data_tls_index));
if (!threadData) {
QThread *adopted = 0;
if (QInternal::activateCallbacks(QInternal::AdoptCurr entThread, (void **) &adopted)) {
Q_ASSERT(adopted);
threadData = QThreadData::get2(adopted);
TlsSetValue(qt_current_thread_data_tls_index, threadData);
adopted->d_func()->running = true;
adopted->d_func()->finished = false;
static_cast<QAdoptedThread *>(adopted)->init();
} else {
threadData = new QThreadData;
// This needs to be called prior to new AdoptedThread() to
// avoid recursion.
TlsSetValue(qt_current_thread_data_tls_index, 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();
}

if (!QCoreApplicationPrivate::theMainThread) {
QCoreApplicationPrivate::theMainThread = threadData->thread;
} else {
HANDLE realHandle = INVALID_HANDLE_VALUE;
#if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600))
DuplicateHandle(GetCurrentProcess(),
GetCurrentThread(),
GetCurrentProcess(),
&realHandle,
0,
FALSE,
DUPLICATE_SAME_ACCESS);
#else
realHandle = (HANDLE)GetCurrentThreadId();
#endif
qt_watch_adopted_thread(realHandle, threadData->thread);
}
}
return threadData;
}

Because the parent is nil , so it will go to QThreadData::current(), because it's the first time to call QThreadData::current(), so it will jump to line "threadData = new QThreadData" to create threadData . the ref of d->threadData->ref will create the reference of threadData next time. that's the problem! because i found that the ref of threadData is not equal to 0 when the application exit. so it raise the memory leak.

is it clear?

Thanks appreicat for any advice!

TMan
25th February 2010, 10:53
If you would've checked the destructor of QObject you would've seen this:


d->threadData->deref();

which should get to this:


void QThreadData::deref()
{
#ifndef QT_NO_THREAD
if (!_ref.deref())
delete this;
#endif
}

In other words, it seems that you yourself are not deleting the object. Perhaps you should consider changing your global object (why have a global object in the first place? Maybe you could use a singleton instead?) with a pointer to this object. You can then easily delete it at the end of your program.

yxtx1984
26th February 2010, 02:16
Yes, it will go to QThreadData::deref(), but the problem is that the _ref.deref is not equal to 0 when the application is going to exit.
The object will call destructor by itself when the application exit.
I will try to use a singleton.
Thanks!

yxtx1984
26th February 2010, 08:00
And i find that there is the same problem with the demo of Qt. So can anyone tell me that wether is real memory leak or just the detect tool lies?

TMan
26th February 2010, 12:13
Yes, it will go to QThreadData::deref(), but the problem is that the _ref.deref is not equal to 0 when the application is going to exit.
The object will call destructor by itself when the application exit.
I will try to use a singleton.
Thanks!

I don't get it. If _ref.deref != 0 QThreadData::deref should call "delete this", which seems to be what you want?

Which tool are you using to check for memory leaks? Do you compile without optimization? Compile with (aggressive) optimization may give false results.

If you still have problems, maybe you could supply a small program which exactly demonstrates the problem.