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





______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to