Hello all,
I have an issue with STL std::map. Here's a quick description. I have a member in SPConnectorContext structure that is a map:
std::map<SPKnot* , ConnectionPoint> connpthandles;
Having the following code in a function produces a sigfault:
cc->connpthandles[knot] = it->second;
where cc is a pointer to SPConnectorContext. I have also defined a local variable
std::map<SPKnot*, ConnectionPoint> cph_clone;
and the following instruction executes all right
cph_clone[knot] = it->second;
It seems that somehow the connpthandles map gets scrambled or improperly initialized. I don't know why this is so. Any help is welcome.
Regards, Arcadie
Arcadie M. Cracan wrote:
Having the following code in a function produces a sigfault:
cc->connpthandles[knot] = it->second;
I hope you'll tolerate my rather long explanation. If you'd rather get the fix right away, skip the next paragraph :)
SPConnectorContext is a GObject, not a normal C++ object, and does not have a constructor or a destructor. Because of this, constructors and destructors for its members are not invoked either. For primitive values it makes little difference, because usually the memory where the GObject resides is zeroed before use, but when the object has a non-trivial constructor and/or destructor, it causes undefined behavior (usually a segfault like in your case, but all kinds of sinister things could happen). You need to invoke the constructors and destructors of member objects yourself in the 'init' and 'dispose' functions used by the GObject system. The constructor is invoked using placement new, and the destructor by calling it directly. The syntax might be a bit of mystery, because you won't find this in most C++ books: you never need to do this if you are using normal C++ objects unless you are writing an allocator, and most programmers won't ever need to write one.
Now the actual solution. You need to put this somewhere in sp_connector_context_init:
new (&cc->connpthandles) std::map<SPKnot* , ConnectionPoint>();
and this in sp_connector_context_dispose:
cc->connpthandles.~std::map<SPKnot* , ConnectionPoint>();
You can also add 'typedef std::map<SPKnot* , ConnectionPoint> PointMap;' somewhere so that those lines are simplified to:
new (&cc->connpthandles) PointMap(); cc->connpthandles.~PointMap();
respectively. I'm not surprised you were hit by this, because it's not very obvious and your event context did not contain any C++ objects until now.
Regards, Krzysztof
On Wednesday 12 August 2009 02:15:06 am Krzysztof Kosiński wrote:
I hope you'll tolerate my rather long explanation. If you'd rather get the fix right away, skip the next paragraph :)
Thank you for having the time to write the exhaustive explanation.
Now the actual solution. You need to put this somewhere in sp_connector_context_init:
new (&cc->connpthandles) std::map<SPKnot* , ConnectionPoint>();
and this in sp_connector_context_dispose:
cc->connpthandles.~std::map<SPKnot* , ConnectionPoint>();
Yes, this solved my problem. Thank you again.
Regards, Arcadie
participants (2)
-
Arcadie M. Cracan
-
Krzysztof Kosiński