Undefined reference error when using a simple class inside my function - c++

I am getting nuts with this error so I thought some of more experienced developers can help me in this regard.
I am trying to compile a sample project which uses a C++ library (named Poco). My project is linked to compiled poco libraries.
Below is my (most simplified) code:
#include "Poco/UUID.h"
class x
{
void func1()
{
new Poco::UUID(); //A
}
};
void func1()
{
new Poco::UUID(); //B
}
Now when above code is compiled, line 'A' has no error but for line 'B' linker says:
undefined reference to `Poco::UUID::UUID()'
What is the reason? When I instantiate a class from external lib in a class method no error occurs but the same code in a function produces linker error? (When I comment line B, no error occurs and linker output files are generated)
My configuration: Win7/g++/CodeLite/MinGW-4.7.1
*Update 2:*Thanks. My problem is now resolved and the issue is that I had compiled library using MSVC compiler while my application was being compiled using g++ (both under Windows platform). So I re-compiled library using g++ and everything works fine now.
Update 1: here is my IDE's output when I build my project:
C:\Windows\system32\cmd.exe /c "mingw32-make.exe -j 4 -e -f "dll1.mk" all"
----------Building project:[ dll1 - Debug ]----------
g++ -shared -fPIC -o ./Debug/dll1.so #"dll1.txt" -L. -Lc:/poco/lib -lPocoFoundationd
./Debug/PluginLibrary.o: In function `Z5func1v':
C:/Users/PARS/Documents/codelite/workspace1/dll1/PluginLibrary.cpp:12: undefined reference to `Poco::UUID::UUID()'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe: *** [Debug/dll1.so] Error 1
dll1.mk:77: recipe for target `Debug/dll1.so' failed
1 errors, 0 warnings

Your member function x::func1() is never ODR-used in that compilation unit (source file). Most compilers only generate compiled code for a member function defined inside the class definition if that member function is ODR-used within the compilation unit that is being compiled. Suppose some other source file does use x::func1(). If you compile that other source file, the compiler will produce object code for x::func1() in the object file that corresponds to that other source file.
The compiler can get away with bypassing the process of generating compiled code for x::func1() here because the class definition has to be the same across all compilation units. If you compile some other source file that has a different definition of class x you have violated the one definition rule. This is undefined behavior and no diagnosis is required.
If no source file uses x::func1() you have some dead code that just never happens to be compiled. The code has an error but it's never detected.
The compiler cannot get away with bypassing generating compiled code for the free function func1(). This function has external linkage; there's no way the compiler can tell if it might be used somewhere else. The compiler must generate compiled code for that free function.
Here's a minimum working example:
class Missing {
public:
Missing();
int value;
};
class UsesMissing {
public:
int use_missing () {
Missing missing;
return missing.value;
}
int dont_use_missing () {
return 0;
}
};
#ifdef DEFINE_USE_MISSING
int use_missing () {
Missing missing;
return missing.value;
}
#endif
int main () {
UsesMissing test;
#ifdef USE_MISSING
return test.use_missing();
#else
return test.dont_use_missing();
#endif
}
Compile with neither DEFINE_USE_MISSING or USE_MISSING defined and this compiles and links just fine with g++ and clang++. Define either one of those flags and the file fails in the link step because of the undefined reference Missing::Missing().

You should link with the correct library to fix your link (see Poco docu for the correct one).
func1 has extern linkage and so linker need Poco::UUID
whereas X::func1 is inline/private/unused.
if you use static foo1() or inline foo1() the linker error disappears
if you use x::func1 or implement x::func1 outside of the class x{}; the error linker appears

Related

if vtable is created at compile time , why this error is an linker error and not compile error?

The following piece of code give me the error
undefined reference to `vtable for Derived'
Code :
#include <iostream>
class base{
public:
base(){}
virtual ~base(){}
virtual void test()
{
}
};
class Derived:public base{
public:
Derived(){}
~Derived(){}
void test();
};
int main() {
base* b = new Derived ();
delete b;
}
which i understand is because the virtual fucntion test is declared but not defined in class Derived.
But when i compile with g++ -c file.cpp which as per this Compile or assemble the source files, but do not link. It does not give me any errors and compiles fine. Hence the above error is generated at linking time and not compile time.
From what i learned wasn't the vtable created at compile time. Then why do i not get the error at compile time itself?
However you formed the view that a vtable must be created at compile time, you are mistaken.
Separate compilation is a core concept in the standard. It is the reason that a compilation unit (aka source file) can compile, given any declaration of a function it needs - even if it doesn't have visibility of the definition.
In the typical "compile then link" build chain, this allows a compilation unit (source file) to compile, given any declaration of a function (member function or not) that might be defined in another compilation unit.
The absence of the definition of a function then needs to be detected by the linker.
Practically, this means that the compiler may emit information about the vtable, but it will be the linker that (ahem) links the specification of the vtable to the actual member functions.
Compiler doesn't require to have all methods available. It's enough for him to have their declaration.
This method could be implemented in different compilation unit (cpp/cxx file) so for compiler it's not even possible to check if this method is available somewhere else. Compiler process one cpp file at time.
It's linker job to match methods and calls together.
What I get with g++ foo.cpp -v
/tmp/ccBc4VPu.o: In function `Derived::Derived()':
foo.cpp:(.text._ZN7DerivedC2Ev[_ZN7DerivedC5Ev]+0x1f): undefined reference to `vtable for Derived'
collect2: error: ld returned 1 exit status
That's a linker error, not a compiler error per se.
The root cause of the error is that test is declared in Derived, but not actually implemented. The linker is giving a confusing error message. It should be declaring an error for the missing Derived::test method
GCC has an FAQ entry for this problem:
When building C++, the linker says my constructors, destructors or virtual tables are undefined, but I defined them
The solution is to ensure that all virtual methods that are not pure are defined. Note that a destructor must be defined even if it is declared pure-virtual [class.dtor]/7.

g++ fails to link .o files into an executable

I am doing an example drill in the textbook I am using to learn from. All I need to do is compile, link and run the following 3 files:
//file my.h
extern int foo;
void print_foo();
void print(int);
my.h is a simple header file that declares the two functions and a 'global' int foo, with no initial value.
//file my.cpp
#include "my.h"
#include "std_lib_facilities.h" //not included but not source of error
void print_foo()
{
cout << foo << endl;
}
void print(int i)
{
cout << i << endl;
}
my.cpp contains the implementation of the functions included from my.h. std_lib_facilities.h is a file from the textbook, and is not the source of error (according to g++). I can edit it into the body of the question if needed.
//file use.cpp
#include "my.h"
#include <iostream>
int main() {
foo = 7;
print_foo();
print(99)
char cc; cin >> cc;
return 0;
}
use.cpp serves as the main implementation file in this program, and tries to use all three declared & defined objects.
I took the two step command approach to build using g++. First, I compiled both .cpp files:
g++ -c my.cpp use.cpp
which created two object files, my.o and use.o. I used the following command to link them:
g++ -o myprog my.o use.o
giving me this error:
Undefined symbols for architecture x86_64:
"_foo", referenced from:
print_foo() in my.o
_main in use.o
(maybe you meant: __Z9print_foov)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I have tried putting
int foo;
into my.h instead of
extern int foo;
which gave me the same error.
I have tried using the
-std=c++11
flag as well which resulted in the same error.
I am using a MacBook Pro with the latest macOS (just updated in fact), if that helps with interpreting the error message.
I have tried to initialize foo, which didn't change anything.
In addition, I have tried updating the command line tools, same error.
From what I understand, the error is telling me that, even though my.h is included in both files, neither one can actually implement any function using the foo variable (which it calls _foo), despite it being explicitly declared in my.h. My guess is that the linker is using the wrong names under the hood, which make it impossible to link into an executable. This comes from the fact that the error mentioned a
__Z9print_foov
which exists nowhere in any of the files.
It almost seems like a g++ or macOS/Command Line Tools bug at this point. I don't want to add the declarations each time, because that creates duplicate symbol errors anyway. Putting my.cpp and use.cpp into one file would probably link properly, but I need to make sure that I can actually link multiple cpp files, because I will eventually (hopefully) be working with multiple cpp files that need to be linked. Any help is appreciated!
Here you declare a variable:
extern int foo;
and you use the variable:
cout << foo << endl;
but you did not define the variable anywhere. The linker error says that the linker could not find the variable's definition. To fix this, put int foo; at file scope in one of the .cpp files.
In the question you say that changing extern int foo; to int foo; gives the same error. However if you look more carefully at the error message I think you will find that it gives a different one, about multiple definitions.
I suggest to compile in two commands g++ -Wall -c my.cpp (that gives a my.o) and g++ -Wall -c use.cpp (giving use.o), then link a program with g++ my.o use.o -o myprog. Actually you should write a Makefile (see this for inspiration) and simply run make
Your translation units my.cpp and use.cpp are both declaring some extern int foo; variable which is never defined. So you need to define it in one single file (but not in others!), probably by adding (into my.cpp alone for example)
int foo;
(without the extern) or even with some explicit initial value e.g. int foo = 34;
This comes from the fact that the error mentioned a __Z9print_foov which exists nowhere
It is a mangled name, which is referenced (but not defined) in both object files (see also this).
It almost seems like a g++ or macOS/Command Line Tools bug at this point
You are very unlikely to find bugs in compiler tools (both GCC & Clang/LLVM are extremely well tested; since they are multi-million lines free software, they do have residual bugs, but you have more chances to win at the lottery than to be affected by a compiler bug). I'm coding since 1974, and it happened to me only once in my lifetime. A more realistic attitude is to be more humble, and question your own code (and knowledge) before suspecting the compiler or build chain.
BTW, always compile first with all warnings and debug info (e.g. g++ -Wall -g and perhaps also -Wextra). Use the gdb debugger. When you are convinced that your code has no bugs, you might benchmark it by asking the compiler to optimize (so use g++ -Wall -O2 perhaps also with -g to compile).
Read also the linker wikipage. Dive into your C++ textbook (see also this site and the C++11 standard, e.g. n3337 draft) to understand the difference between declaring and defining some variable or function. You generally declare a global extern variable in some common header (included in several translation units), and define it once somewhere else, but the good practice is to avoid having lots of global variables. See also C++17 new inline variables.

Error launching C++ executable in AIX

I am facing a unique problem as part of our application migration from HP to AIX.
The following simulated code produces different results in HP and AIX.
library.C **
#include <stdio.h>
#include "mylib.h"
int libimgclientFNXXX()
{
int check = 100;
check = FileNetDeleteDoc(check);
return check;
}
int libimgclientFN()
{
int check = 1;
printf("In lib ");
return check;
}
* main_func.C *
#include <stdio.h>
int libimgclientFN();
int libimgclientFNXXX();
int main()
{
int one = 0;
if (1 == 1)
{
one = libimgclientFN();
}
printf("\n The status is %d \n", one);
}
* mylib.h **
extern int FileNetDeleteDoc (int);
Note that the function libimgclientFNXXX() is never called.
My make file is as below:
xlC -c -g library.C -o library.o -I./
xlC -G -qmkshrobj -o libImgClient.so library.o
xlC -c -g -qpic=small main_func.C -o main_func.o
xlC -brtl main_func.o -L. -lImgClient -o TST
When I run TST, I get the following loading error
$ TST
exec(): 0509-036 Cannot load program TST because of the following errors:
rtld: 0712-001 Symbol FileNetDeleteDoc__Fi was referenced
from module ./libImgClient.so(), but a runtime definition
of the symbol was not found.
Even though the function libimgclientFNXXX() is never called, there is unresolved errors.
The exact same code built in HP works fine with no errors.
Any inputs is appreciated.
Thanks,
Yeah, "not using" a library function may still be an error, even if you are not going to call the code. It MAY defer the loading of some componanent until later, so it MAY not cause an error. Best not to have references to things that don't exist (or manually load the library and get the address, if the function doesn't exist, you'll get an error from the "find the function" call and you can do something sensible in the code).
The loader (the code that loads binary executables) isn't very clever, so it can't know exactly what is being called and what isn't. It's also possible that different compilers have different levels of cleverness for "dead code removal", so the one compiler completely removes the "never called" function, but another compiler doesn't remove it [because it's not got the cleverness to 100% certify that you never call the function - in gcc for example, it would know this if you made the libimgclientFNXXX a static function - because it knows that static functions don't get called outside this module, and this module isn't using it.
AIX requires all symbols to resolve at load-time, so even though it builds OK, because the symbol is referenced the applications will not run.
You need to use lazy linking for the .so (the -blazy link option), which should cause the missing function to be linked only on first use.
You really should not be leaving undefined symbols in a library, though - if it needs symbols from another library, you should be linking to them (unless it's a plug-in, where the symbol is exposed in the app itself).

symbol lookup error

I am writing a shared library with C++ under Ubuntu. The source code contains two files: ClassA.h and ClassA.cpp. Bellow are parts of the contents:
ClassA.h:
namespace calss_a{
class ClassA{
public:
...
void foo(int nBlockIndex);
...
}
}
ClassA.h:
namespace calss_a{
...
void classA::foo(int nBlockIndex){printf("....");}
...
}
The compiled .so file from the above source codes is used in test.cpp as follows:
...
class_a::ClassA * ptr = new class_a::ClassA();
...
ptr->foo(0);
...
However, when the executable build from test.cpp runs, there is an error as follows:
symbol lookup error: /home/hzhu/test: undefined symbol: _ZN16class_a15ClassA16fooEj
But if I change in ClassA.cpp and ClassA.h the type of foo()'s argument "nBlockIndex" from "int" to "unsigned in", and recompile the .so file, then the problem disappears. In a further experiment, the argument "nBlockIndex"'s type is still defined to be "int", but in test.cpp I call "foo" this way:
ptr->foo(1); //pass 1 instead of 0
then the problem disappear as well.
Can anyone tell me what is going on here?
Thanks.
I am a bit new to this kind of thing myself, but I am also running into a symbol lookup error and so thought I would share what I have found out.
The problem with symbol lookup errors usually is that something is being defined two different ways in two different places. If you do
nm -u your-executable | grep undefined-symbol
then you will find out where the symbols being used in an object file or executable file are defined

Undefined reference linking error when using &MyClass::MyFunction

this just has me stumped, so I thought I'd query here:
I have a class as follows:
class MyClass {
public:
void myThreadFunc();
};
That's in the header. In the constructor
MyClass::MyClass() {
...
boost::thread t(boost::bind(&MyClass::myThreadFunc, this));
...
}
As I've seen done. There are NO compile time errors. However, when I link as follows:
g++ -o test.exe main.o MyClass.o /*specify boost and other libraries */
I get:
MyClass.o:MyClass.cpp:(.text+0xa4): undefined reference to `MyClass::myThreadFunc()'
collect2: ld returned 1 exit status
Which doesn't make any sense. What strikes me especially odd is that's its a linker error. I included both of my object files.
Can anyone tell me what's going on? If it might be relevant, I'm on MinGW on Windows.
EDIT:
Epic fail. I forgot the MyClass:: prefix when defining the function in my cpp file. I just didn't decide to check that. Almost as bad as forgetting a semicolin after a class definition.
You need to write a function body for MyClass::myThreadFunc() somewhere. Writing a constructor for MyClass is different from implementing the MyClass::myThreadFunc() member function.
If you call a function in C/C++, it must have a function body somewhere. That's why it's a linker error; it's trying to find the function body in all of the available object files, but you didn't write one so it can't.