8

We have a large code base in C++ and after a smallish refactor (one class added and some related methods rewritten), we started getting linker errors on GCC 3 & 4. The linker errors were specifically "missing references to non-virtual thunks" in small sample programs that subclassed classes in our large SDK.

Searching the web didn't give many hints beyond some old GCC bugs that seem to have been resolved.

The attributes of the problem seem to be:

  • GCC 3.4.6 & 4.3.3 optimizing with -O2
  • Multiple inheritance, including occasional virtual inheritance.
  • Changing the inheritance order from, say,
    class Foo: public A, public B {} to
    class Foo: public B, public A {}
    on the classes that are missing the thunks "fixes" the problem.

The virtual inheritance only appears in a single, very-commonly used base class for reference counting. I have verified that every usage of this class really is virtual public, and not just public inheritance by accident.

Obviously fiddling with the inheritance order is not really solving the problem. What else could it be?

random
  • 9,774
  • 10
  • 66
  • 83
Adrian
  • 1,842
  • 13
  • 25
  • Are you using the same optimization level for linking against a library that you used to compile your library? – Karl von Moor Apr 14 '11 at 15:47
  • Have you recompiled the whole program, libs, resource files, pch after the change ()? – RedX Apr 15 '11 at 15:15
  • We have a validation build that builds everything fresh every time it gets checked into source control, so yes. – Adrian Apr 15 '11 at 17:13
  • Or, rather, we do have fixed pre-compiled third-party libraries like Boost, etc, but all our code is rebuilt every time. – Adrian Apr 15 '11 at 17:14
  • 8
    This message could mean that a virtual function is declared, but not defined (or a definition is not linked in). It could be something else though. Could you please quote one of the error message verbatim? – n. m. could be an AI Dec 20 '11 at 05:58
  • -O2 is a common place of problem for some cases. I also faced a problem with this in g++4.4.x compiler. – siddhusingh Apr 05 '12 at 11:28
  • 1
    Something to keep in mind is that generally speaking there is no guarantee that you can link code from different c++ compilers or even different versions of the same c++ compiler. They use different conventions to implement c++ features. – NovaDenizen Sep 04 '12 at 04:10
  • I had some problems with some early versions of gcc and virtual functions. The solution was to reorder the order of appearance of virtual functions and make it the same on all classes. You can check and see if such an issue is the cause of your problems. – ipapadop Oct 02 '12 at 18:14
  • I would try rebuilding Boost and other third party (static) libraries. If you're dynamically linking you should be relatively safe, I think. – Mark McKenna Oct 10 '12 at 13:42
  • In a case like this, if you need to stay with -O2, I would try to use a much newer version of gcc. Or try out clang. Then recompile everything including external libraries if possible. – Johan Lundberg Oct 14 '12 at 18:06
  • Thanks for all the suggestions! Unfortunately I don't have access to the codebase anymore, but I'll leave this here in case it helps someone else in the future. – Adrian Oct 16 '12 at 19:11
  • @ipapadop, that would have been a gross violation of the C++ definition. I'd expect to see something like that in the very first betas of a C++ compiler at the latest. – vonbrand Feb 08 '13 at 04:55
  • @vonbrand I agree and I only saw it once in my life in some gcc 3.x – ipapadop Feb 08 '13 at 05:17

2 Answers2

1

If changing the declaration order of the base classes fix the issue, it probably means that one of the base class doesn't properly define what it declared.

For example, if you have a declaration with a (not virtual) method Func in class A and the same in class B but you never defined it for class A, then the first time the method is called in your child, the class A's version is called, but at link time, the reference is not found. If you change inheritance order, will make the compiler call B::Func instead, which is defined and then the linker will find it.

IMHO, it's a bad design anyway, since there behaviour will be hard to predict and to debug.

xryl669
  • 3,376
  • 24
  • 47
0

It could be the diamond problem

if so Check this thread

Community
  • 1
  • 1
DjSol
  • 208
  • 1
  • 11