g++ giving errors where visual studio was happy - undefined reference
I have some code that runs fine on Visual Stu开发者_C百科dio, and I am now trying to compile it on g++. It is giving me 'undefined reference to SomeClass::someMethod() const' in a bunch of places.
Most commonly, it's the following situation:
for (const SomeListNode *node = owner->some_list; node != 0; node = node->getNext())
In this case, I get 'undefined reference to SomeListNode::getNext() const'. This class's header file is explicitly included. Why is this not legal in g++?
edit for more info
I am building with a makefile as such:
CC=g++
CFLAGS=-c -Wall -DDEBUG -g
LDFLAGS=
SOURCES=main.cpp SomeList.cpp SomeListNode.cpp Location.cpp OutputControl.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=theprogram
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $@
.cpp.o: $(CC) $(CFLAGS) $< -o $@
The line of code originally listed is in the OutputControl.cpp
. It is taking a pointer to a SomeListNode
and iterating over it. getNext
() returns a pointer to another SomeListNode
.
It may also be of note that this is only occurring within static functions.
You can only call const-qualified methods on a const-qualified object. If getNext() is not const, then you should use SomeListNode *node
instead of const SomeListNode *node
.
Undefined references are linker errors, and these are unrelated to header inclusions. You have to make sure that you have compiled the definitions of those functions into some object file, and that the object file is passed to the linker.
Beware that if you are compiling to static libraries, the order of the libraries in the linker command line affects the result. In particular, if a library depends on other libraries, the dependent should appear in the command line before all the depended on libs.
At any rate, compile each object file separately into a .o or a library and use nm to extract the list of symbols that is defined in each one of the translation units that should tell you whether the definition has been compiled or not and will help you determine the order if you are compiling static libs.
I would suggest that you set up dependencies in your makefile so that objects that depends on others are made in the correct order. Also setup a clean target that deletes .o files. After this run make clean, and make.
This is the best suggestion I can think of with the information you have given us.
Pass all your .cpp files to the g++ compile command.
g++ -g -Wall -o myapp File1.cpp File2.cpp File3.cpp
EDIT:
If you're using static libraries, you should add these last on the g++ commandline.
The linker processes passed files in order, and when it encounters a static library it searches for symbols that are undefined so far. You can change this using --whole-archive
I recommend to use the nm
tool to find out which symbols are involved in you situation. It may look like this:
// foo.h
class Foo{
public:
void bar();
};
// foo.cpp
#include "foo.h"
void Foo::bar()
{
}
// bar.cpp
#include "foo.h"
void baz()
{
Foo f;
f.bar();
}
> nm foo.o
00000000 T _ZN3Foo3barEv
> nm bar.o
00000000 T _Z3bazv
U _ZN3Foo3barEv
U __gxx_personality_v0
Here you can see, that bar.o uses an undefined _ZN3Foo3barEv
symbol (and a __gxx_personality_v0
, but this is a compiler detail), which is marked U
. This symbol is defined in foo.o
, wehre it is marked T
. To get the c++ name form the mangled name, you can use c++filt
.
> c++filt _ZN3Foo3barEv
Foo::bar()
> c++filt _Z3bazv
baz()
To debug your problem you inspect both your SomeList.o and OutputControl.o files and look for SomeListNode::getNext instances. There might be lots of output, so you might want to filter the output with nm file.o | grep 'SomeListNode.*getNext'
. Every U
marked SomeListNode::getNext
symbol form your OutputControl.o file must have an exact match in your SomeList.o file.
Edit: Adjusted answer to the posted Makefile.
One difference between Visual Studio and g++ is how they deal with templates. In Visual Studio, if you define a function in a template, but you never use it anywhere, VS won't typecheck it or generate any code. In g++ it will typecheck (and it'll give you errors if there are any problems in it).
精彩评论