From murdoch.duncan at gmail.com  Wed Oct  2 22:55:31 2013
From: murdoch.duncan at gmail.com (Duncan Murdoch)
Date: Wed, 02 Oct 2013 16:55:31 -0400
Subject: [Rd] C++ debugging help needed
In-Reply-To: <1380746252.7443.32.camel@localhost>
References: <524C32CF.2060307@gmail.com> <524C362F.1040108@gmail.com>
	<20131002200118.GX32066@markov.biostat.ucsf.edu>
	<524C7EFC.5030605@gmail.com> <1380746252.7443.32.camel@localhost>
Message-ID: <524C8843.1030203@gmail.com>

On 13-10-02 4:37 PM, Ross Boylan wrote:
> On Wed, 2013-10-02 at 16:15 -0400, Duncan Murdoch wrote:
>> On 02/10/2013 4:01 PM, Ross Boylan wrote:
>>> On Wed, Oct 02, 2013 at 11:05:19AM -0400, Duncan Murdoch wrote:
>>> ....
>>>>> Up to entry #4 this all looks normal.  If I go into that stack frame, I
>>>>> see this:
>>>>>
>>>>>
>>>>> (gdb) up
>>>>> #4  Shape::~Shape (this=0x15f8760, __in_chrg=<optimized out>) at
>>>>> Shape.cpp:13
>>>>> warning: Source file is more recent than executable.
>>>
>>> That warning looks suspicious.  Are your sure gdb is finding the right
>>> source files, and that the object code has been built from them?
>>
>> I'm pretty sure that's a warning about the fact that igraph also has a
>> file called Shape.cpp, and the Shape::~Shape destructor was in that
>> file, not in my Shape.cpp file.
>
> I guess the notion of the "right" source file is ambiguous in this
> context.  Suppose you have projects A and B each defining a function f
> in f.cpp.  Use A/f() to mean the binary function defined in project A,
> found in source A/f.cpp.
>
> The you have some code that means to invoke A/f() but gets B/f()
> instead.  Probably gdb should associate this with B/f.cpp, but your
> intent was A/f() and A/f.cpp.  If gdb happens to find A/f.cpp, and A was
> build after B, that could provoke the warning shown.
>
>>>
>>>>> 13        blended(in_material.isTransparent())
>>>>> (gdb) p this
>>>>> $9 = (Shape * const) 0x15f8760
>>>>> (gdb) p *this
>>>>> $10 = {_vptr.Shape = 0x7ffff2d8e290, mName = 6, mType = {
>>>>>        static npos = <optimized out>,
>>>>>        _M_dataplus = {<std::allocator<char>> =
>>>>> {<__gnu_cxx::new_allocator<char>> =
>>>>> {<No data fields>}, <No data fields>},
>>>>>          _M_p = 0x7f7fffff7f7fffff <Address 0x7f7fffff7f7fffff out of
>>>>> bounds>}},
>>>>>      mShapeColor = {mRed = -1.4044474254567505e+306,
>>>>>        mGreen = -1.4044477603031902e+306, mBlue = 4.24399170841135e-314,
>>>>>        mTransparent = 0}, mSpecularReflectivity = 0.0078125,
>>>>>      mSpecularSize = 1065353216, mDiffuseReflectivity = 0.007812501848093234,
>>>>>      mAmbientReflectivity = 0}
>>>>>
>>>>> The things displayed in *this are all wrong.  Those field names come
>>>>> from the Shape object in the igraph package, not the Shape object in the
>>>>> rgl package.   The mixOmics package uses both.
>>>>>
>>>>> My questions:
>>>>>
>>>>> - Has my code somehow got mixed up with the igraph code, so I really do
>>>>> have a call out to igraph's Shape::~Shape instead of rgl's
>>>>> Shape::~Shape, or is this just bad info being given to me by gdb?
>>>>>
>>>
>>> I don't know, but I think it's possible to give fully qualified type
>>> names to gdb to force it to use the right definition.  That's assuming
>>> that both Shape's are in different namespaces.  If they aren't, that's
>>> likely the problem.
>>
>> Apparently they aren't, even though they are in separately compiled and
>> linked packages.  I had been assuming that the fact that rgl knows
>> nothing about igraph meant I didn't need to worry about it. (igraph does
>> list rgl in its "Suggests" list.)  On platforms other than Linux, I
>> don't appear to need to worry about it, but Linux happily loads one,
>> then loads the other and links the call to the wrong .so rather than the
>> local one, without a peep of warning, just an eventual crash.
>
> While various OS's and tricks could provide work-arounds for clashing
> function definitions (I actually had the impression the R dynamic
> loading machinery might) those wouldn't necessary be right.  In
> principle package A might use some functions defined in package B.  In
> that case the need for namespaces would have become obvious.

The issue is that I don't need to import the problematic function from 
another library.  It is not defined in the same .o file, but it is in 
the same .dll/.so.   I think the linker should have resolved it, not 
left it for later resolution by the loader.

I would expect to have problems if functions like Rprintf() were defined 
in multiple places, because I need to import those.  But I think it's a 
linker bug (or a bad design) in a case where the function is defined in 
another .o file being linked into a shared library.

Duncan Murdoch

>
>>
>> Supposing I finish my editing of the 100 or so source files and put all
>> of the rgl stuff in an "rgl" namespace, that still doesn't protect me
>> from what some other developer might do next week, creating their own
>> "rgl" namespace with a clashing name.   Why doesn't the linking step
>> resolve the calls, why does it leave it until load time?
>
> I think there is a using namespace directive that might save typing,
> putting everything into that namespace by default.  Maybe just the
> headers need it.
>
> With dynamic loading you don't know til load time if you've got a
> problem.  As I said, the systemm can't simply wall if different
> libraries, since they may want to call each other.
>
> The usual solution for two developers picking the same name is to have
> an outer level namespace associated with the developer/company/project,
> with other namespaces nested inside.  This reduces the problem, though
> obviously it can still exist higher up.
>
> Ross
>>
>>
>>>> - If I really do have calls to the wrong destructor in there, how do I
>>>> avoid this?
>>
>> Are you invoking the destructor explicitly?  An object should know
>> it's type, which should result in the right call without much effort.
>>
>>
>> No, this is an implicit destructor call.  I'm deleting an object whose
>> class descends from Shape.
>>
>> Duncan Murdoch
>>
>>
>
>



[Rd] C++ debugging help needed
Duncan Murdoch