Qt-interest Archive, March 2002
crash in QMap<T,T> copy constructor (fwd)
Message 1 in thread
The attached code may crash if the static member is initialised _after_
Foo. No the attachment doesn't crach, but I have an application that do
so.
QMap( const QMap<Key,T>& m )
{
sh = m.sh; sh->ref(); // crash, cause m.sh is 0
}
qt-x11-free-3.0.2
SuSE Linux 7.3
gcc 2.95.3
#include <qmap.h>
class Foo {
public:
Foo (QMap<int, int> _map = nullMap)
: map(nullMap)
{}
void run(){}
static const QMap<int, int> nullMap;
QMap<int, int> map;
};
const QMap<int, int> Foo::nullMap;
int main(){
Foo foo;
foo.run();
}
Message 2 in thread
yup - hit that one before. You need to rethink how you're doing things.
The problem is that C++ does not say anything about the order of creation
(and initialization) of static member variables. If you're using a static
member object that has it's own static member objects, you're playing with
fire because you can't guarantee who'll be initialized first.
Here's an even simpler crash (if you link statically):
////////////////
#include <qstring.h>
QString l_CRASH = QString::null;
int main( int argc, char ** argv )
{
return 0;
}
////////////////
It'll explode because the QString global constructor is crashing trying to
do a shallow copy of QString::null.
j
-----Original Message-----
From: Wenzel P. P. Peppmeyer [mailto:wenzel.peppmeyer@gmx.de]
Sent: Tuesday, March 26, 2002 11:06 AM
To: qt-interest@trolltech.com
Subject: crash in QMap<T,T> copy constructor (fwd)
The attached code may crash if the static member is initialised _after_
Foo. No the attachment doesn't crach, but I have an application that do
so.
QMap( const QMap<Key,T>& m )
{
sh = m.sh; sh->ref(); // crash, cause m.sh is 0
}
qt-x11-free-3.0.2
SuSE Linux 7.3
gcc 2.95.3
Message 3 in thread
On Tue, 26 Mar 2002, Jason Bright wrote:
> yup - hit that one before. You need to rethink how you're doing things.
>
> The problem is that C++ does not say anything about the order of creation
> (and initialization) of static member variables. If you're using a static
> member object that has it's own static member objects, you're playing with
> fire because you can't guarantee who'll be initialized first.
Playing with zero pointers in copy constructors hurts too.
Message 4 in thread
On Tuesday 26 March 2002 02:08 pm, Wenzel P. P. Peppmeyer wrote:
> On Tue, 26 Mar 2002, Jason Bright wrote:
> > yup - hit that one before. You need to rethink how you're doing things.
> >
> > The problem is that C++ does not say anything about the order of creation
> > (and initialization) of static member variables. If you're using a static
> > member object that has it's own static member objects, you're playing
> > with fire because you can't guarantee who'll be initialized first.
>
> Playing with zero pointers in copy constructors hurts too.
As far as I know, static initialization does have some defined behavior. They
will always construct before any object in a translation unit uses them. They
will always destroy in the reverse order of the completion of their
constructors. If you MUST use statics, this behavior can be leveraged to
insure some runtime safety.
That said, it is still better and often cleaner to avoid the use of statics.
Message 5 in thread
Ho,
> As far as I know, static initialization does have some defined behavior. They
> will always construct before any object in a translation unit uses them. They
No, not if the object that uses them is static.
Dimitri
Message 6 in thread
Hi,
> Playing with zero pointers in copy constructors hurts too.
Sure, but the point is that there are no zero pointers if you
don't use static variables or if you use them with caution.
Static variables often cause problems in C++. These problems
can usually be worked around of course - but you must be aware
of them... which often happens after you've been bitten at
least once.
Dimitri
Message 7 in thread
Greetings, list,
3/26/2002 11:23:04 AM, Jason Bright <JBright@SkyStream.com> wrote:
> ,,, <snip> ...
>#include <qstring.h>
>QString l_CRASH = QString::null;
>... <snip> ....
>It'll explode because the QString global constructor is crashing trying to
>do a shallow copy of QString::null.
Perhaps I'm just ruined for C++ by my more recent experience with Java.
Or perhaps I don't understand one of C++'s "features" properly. But
shouldn't a constructor (like every method on every class) handle any value
of its arguments that the compiler is willing to allow it to see? In particular,
since zero is a legal value for a pointer, isn't it the constructor's obligation
to check for zero do the right thing? (I'd guess that would be just copying the
zero rather than derererencing it.)
That is, isn't this simply a bug in the copy constructor, rather than problem with C++
being underspecified, as Wenzel Peppmeyer suggested?
Regards,
Jerry Barenholtz
jerryb@saltspring.com
Message 8 in thread
Quoth Jerry Barenholtz (on 02/03/27) :
>
> 3/26/2002 11:23:04 AM, Jason Bright <JBright@SkyStream.com> wrote:
>
> > ,,, <snip> ...
> >#include <qstring.h>
> >QString l_CRASH = QString::null;
> >... <snip> ....
> >It'll explode because the QString global constructor is crashing trying to
> >do a shallow copy of QString::null.
>
> Perhaps I'm just ruined for C++ by my more recent experience with Java.
> Or perhaps I don't understand one of C++'s "features" properly. But
> shouldn't a constructor (like every method on every class) handle any value
> of its arguments that the compiler is willing to allow it to see? In
> particular, since zero is a legal value for a pointer, isn't it the
> constructor's obligation to check for zero do the right thing? (I'd
> guess that would be just copying the zero rather than derererencing it.)
>
> That is, isn't this simply a bug in the copy constructor, rather than
> problem with C++ being underspecified, as Wenzel Peppmeyer suggested?
The QString constructor can indeed handle being passed a zero pointer,
but that's not what's happening here.
The problem is that the QString::null static member *hasn't been initialised*
and hence will just be whatever rubbish happens to be at that part of memory.
Thus when the constructor comes to look at it, it starts dealing with junk,
and before long goes bang.
The best way I know of avoiding these problems is to wrap static things
up in functions, eg :
static const QString &nullStringStaticSafe()
{
static const QString null(QString::null);
return null;
}
Cheers,
Anthony
Maptek Adelaide
Anthony Gibbs -- Software Engineer
Email: Anthony.Gibbs@maptek.com.au Phone: +61 8 8338 9225
Dale Cooper: [speaking into tape recorder] Diane, I'm
holding in my hands a small box of chocolate bunnies