PDA

View Full Version : QObject factory (singleton pattern)



area51
24th June 2010, 11:08
Hi, I've been trying to implement an object factory that constructs objects as singleton.
Here's the get_instance of the singleton class, where 'object' refers to a template parameter.



object& get_instance()
{
static object instance__;
return instance__;
}


The use of 'static' gets me into troubles when using a QObject (or any derived instance).
Because QApplication takes control over a QObject's memory, the QObject is already deleted when QApplication is destructed.
After main(), the destructors are called for all static objects, and for those QObjects, this causes a segmentation fault.

Is there a clean way to use 'static' together with QObject?


A simple example to demonstrate the issue on exit:



int main(int argc__, char **argv__)
{
QApplication app__(argc__, argv__);

static QLabel lbl__("Hello world!");
lbl__.show();

app__.exec();

return 0;
}


When closing the label widget, the widget gets deleted twice, resulting in a segmentation fault.


Thanks in advance!

high_flyer
24th June 2010, 11:27
the sample code you posted below does no segmentation fault when I try it.
And I don't see why it should.
Why do you think the label gets destroyed twice?

Because QApplication takes control over a QObject's memor
This is only true if you parent your object to QApplication object, which you didn't int your example.


Hi, I've been trying to implement an object factory that constructs objects as singleton.
Please explain more what you mean, since a factor for singleton is almost an oxymoron.
A singleton can only have one instance of its type,so what for do you need a factory for it?

The problem you have with static is probably bad usage of static.
Show us your full code, or a full relevant segment.

Zlatomir
24th June 2010, 11:29
Can't you redesign? It's recommended to keep separate the GUI and the functionality. And the singleton <i guess> is part of functionality, not GUI, so take him out of QLabel (or other GUI thing).

area51
24th June 2010, 13:07
Thanks guys for the quick reply.

Yes you're right about factory / singleton ;) It's the singleton I want to achieve.
But forget about that, it's just the static part that bothers me.

The sample code does segfault here on my machine. Are you sure you used a static QLabel?
(I'm running on Debian Lenny, Qt-4.6.3, gcc 4.3.2)

Run from command line and close the application properly to notice the cleanup problem (typically by clicking the X in the upper right corner), it won't work if you CTRL-C out of it.

Anyone else who can reproduce the segfault (during application exit)?

high_flyer
24th June 2010, 13:18
I copy- pasted your code.
But I run it on windows.
And it doesn't segfaults when I run it out side the IDE.
You didn't explain why it should.

area51
24th June 2010, 13:55
Strange that it runs fine on Windows... But you might get an unexpected blue screen later today (just kidding)

The label doesn't have QApplication as its parent, it's 0. So I agree that it's not managed by QApplication and it's not deleted twice.
At first sight, I assumed it had something to do with the object tree. My mistake, sorry about the confusion!

The debugger gave me the following backtrace. Still not sure what's happening exactly, but it may explain why it isn't crashing on Windows, because it's clearly inside an X11 class where it segfaults.



(gdb) run
Starting program: test_app
[Thread debugging using libthread_db enabled]
[New Thread 0xb646b6d0 (LWP 12758)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb646b6d0 (LWP 12758)]
0xb70f0f72 in ~QX11WindowSurface (this=0x8190438) at painting/qwindowsurface_x11.cpp:84
84 XFreeGC(X11->display, gc);
(gdb) bt
#0 0xb70f0f72 in ~QX11WindowSurface (this=0x8190438) at painting/qwindowsurface_x11.cpp:84
#1 0xb70eaa55 in ~QWidgetBackingStore (this=0x81902e8) at painting/qbackingstore.cpp:858
#2 0xb6f0802a in QWidgetPrivate::deleteExtra (this=0x818e9c0) at kernel/qwidget.cpp:1622
#3 0xb6f0883f in ~QWidgetPrivate (this=0x818e9c0) at kernel/qwidget.cpp:235
#4 0xb730650d in ~QLabelPrivate (this=0x818e9c0) at widgets/qframe_p.h:62
#5 0xb6b06c78 in ~QObject (this=0x80491a0) at ../../include/QtCore/../../src/corelib/tools/qscopedpointer.h:62
#6 0xb6f194dd in ~QWidget (this=0x80491a0) at kernel/qwidget.cpp:1496
#7 0xb72feed1 in ~QFrame (this=0x80491a0) at widgets/qframe.cpp:242
#8 0xb7305c33 in ~QLabel (this=0x80491a0) at widgets/qlabel.cpp:262
#9 0xb6719481 in __run_exit_handlers (status=0, listp=0xb682d324, run_list_atexit=true) at exit.c:78
#10 0xb67194df in *__GI_exit (status=0) at exit.c:100
#11 0xb6700b5d in __libc_start_main (main=0x8048b64 <main>, argc=1, ubp_av=0xbfffd594, init=0x8048db0 <__libc_csu_init>,
fini=0x8048da0 <__libc_csu_fini>, rtld_fini=0xb77ee9b0 <_dl_fini>, stack_end=0xbfffd58c) at libc-start.c:254
#12 0x08048ad1 in _start ()
(gdb)

high_flyer
24th June 2010, 14:23
Hmm...
I don't know.
It might be a compiler issue, or a Qt system specific implementation issue.
Or- something to do with the a run time dependency which any QPaintDevice has with QApplication- and the way it is (destruction) implemented on Linux.

area51
24th June 2010, 14:36
Could be many things yes... I'm going to avoid the use of static QObjects, until I know more about the details. Unfortunately, I can't spend too much time on it right now.

Thanks again for helping out!

high_flyer
24th June 2010, 14:55
I have implemented QObjects as singletons in the past and I had no problems.
I am quite sure that if you stick to the rules, and don't try exotic things, you wont have any trouble.
I am quite confident that the problem you have is in your code/design and not things out side your code.