GCC: strange unresolved reference on function which doesn't used - c++

#include <iostream>
struct CL1
{
virtual void fnc1();
virtual void fnc2(); //not defined anywhere
};
void CL1::fnc1(){}
int main() {}
This gives an undefined reference error on fnc2, however it isn't used anywhere. Why is this happening? I tried to do it on Visual Studio and then it's linked successfully.

gcc does not remove not used symbols by default at link time,
so for your class with virtual functions, it generate virtual table,
with pointers to each virtual function, and move this table to .rodata section,
so you should receive such error message:
g++ test10.cpp
/tmp/cc5YTcBb.o:(.rodata._ZTV3CL1[_ZTV3CL1]+0x18): undefined reference to `CL1::fnc2()'
collect2: error: ld returned 1 exit status
You can enable garbage collection and link time, and you not receive
and errors:
$ g++ -O3 -O3 -fdata-sections -ffunction-sections -fipa-pta test10.cpp -Wl,--gc-sections -Wl,-O1 -Wl,--as-needed
$

Related

g++ ignores inline keyword (odr) unless diagnostic, optimizer or standard flags are given?

I have these three files:
test.h
inline int foo(int i) {
return i;
}
asdf1.cpp
#include "test.h"
int main () {
}
asdf2.cpp
#include "test.h"
int bar () {
return 42;
}
When compiling with g++ asdf1.cpp asdf2.cpp, this happens:
$ g++ asdf1.cpp asdf2.cpp
/usr/bin/ld: /tmp/ccTPkxPK.o: in function `foo(int)':
asdf2.cpp:(.text+0x0): multiple definition of `foo(int)'; /tmp/ccJLbLeL.o:asdf1.cpp:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
$ g++ asdf1.cpp asdf2.cpp -O1
$ g++ asdf1.cpp asdf2.cpp -Wpedantic
$ g++ asdf1.cpp asdf2.cpp -std=c++14
$ # all of the above work
Why does g++ ignore the inline keyword unless some unrelated flag is given?
Especially weird since, with the -v flag, g++ tells me that it's using c++14 even when nothing is specified. Also, as far as I'm aware, the inline keyword (in this usage) exists in every C++ standard.

Including files correctly , but still getting linker error

hope you guys are doing well. I am just getting linker error in C++ , I don't know why? Everything is correct....
Check below testing.h file
#ifndef __MYClass__
#define __MYClass__
#include<iostream>
using namespace std;
class Abc {
private:
int a;
public:
void input();
void display();
};
#endif
and here's implementation of these functions in Functions.cpp file.
#include"testing.h"
void Abc::input() {
cout<<"Enter any value : ";
cin>>a;
}
void Abc::display() {
cout<<"You Entered : "<<a;
}
And now, in main.cpp
#include<iostream>
#include"testing.h"
using namespace std;
int main() {
Abc obj;
obj.input();
obj.display();
return 0;
}
All files are compiled successfully.
In main.cpp Linker says....
g++ -Wall -o "main" "main.cpp" (in directory: /home/Welcome/C++ Practices/testingLinux)
/usr/bin/ld: /tmp/ccYI9LAy.o: in function main': main.cpp:(.text+0x10): undefined reference to Abc::input()'
/usr/bin/ld: main.cpp:(.text+0x1c): undefined reference to `Abc::display()'
collect2: error: ld returned 1 exit status
Compilation failed.
I'm using built-in linux compiler...
There are multiple ways you can fix this but before that please read up on Translation Unit.
Coming to your problem.
When you write
g++ -Wall -o main main.cpp
The compiler will pick up main.cpp for compilation and expand testing.h that includes the declaration for class ABC and with this header file it can determine what is the size of ABC and be able to generate instructions reserving space for obj on the stack. It can't see the definition for input() and display() hence defers that task to the linker. Note that testing.cpp is not in the picture at all since the compiler doesn't know that the implementation of ABC is in testing.cpp. Now when the linker tries to resolve the symbols input() it fails to find the definition for it and throws the error
undefined reference to Abc::input()
So, to fix this you can tell explicitly upfront that it also needs to take in testing.cpp while compiling main.cpp by
g++ -o main main.cpp testing.cpp
Another way is to create a dynamic library out of testing.h and testing.cpp
g++ -shared -fPIC testing.cpp -o libtest
and then link it against main.cpp
g++ -o main main.cpp -I. -L. libtest
What this does is that the compiler still can't figure out the definition of input() and display() but the linker can since now the library containing the definitions is provided to it.
You are not compiling Functions.cpp file.
This should fix your issue:
g++ main.cpp Functions.cpp

Tracking an issue with -fvisibility=hidden that triggers a undefined reference to `typeinfo for myfunc'

I am trying to compile a project that is written in portable C++. It does compile fine with Visual Studio 2010 on Windows 7 and makes uses of symbol visibilty macros.
However when I compile this project with gcc-4.7 on linux, I am getting this linker error:
g++ -fvisibility=hidden -fvisibility-inlines-hidden [...]
/tmp/ccegevbt.o:(.rodata._ZTI12subclass[_ZTI12subclass]+0x10): undefined reference to `typeinfo for ns::baseclass'
I did read a previous report and indeed exporting at class level directly (instead of per symbol) solves the symptoms, what I would like to understand is why it does not wok at symbol level:
class __attribute__ ((visibility ("default"))) baseclass {
However the code is actually written to export only some member function, so it should produce identical behavior with Visual Studio C++ compiler, right ?
class baseclass {
public: // Member functions
DLL_EXPORT baseclass();
DLL_EXPORT virtual ~baseclass();
My question: is what slightly different behavior in exporting symbols is happening in between Visual Studio 2010 and gcc-4.7 ? How do I track which symbol is actually causing issue ?
For clarification here is a very small toy example which works fine on Visual Studio 2010
$ cat test.h
#pragma once
#ifdef __GNUC__
#define DLL_EXPORT __attribute__((visibility("default")))
#else
#define DLL_EXPORT __declspec(dllexport)
#endif
struct Base
{
DLL_EXPORT virtual ~Base();
DLL_EXPORT virtual Base* clone() {
return 0;
}
};
#undef DLL_EXPORT
and
$ cat test.cpp
#include "test.h"
Base::~Base()
{
}
and
$ cat main.cpp
#include "test.h"
struct Foo : public Base
{
virtual ~Foo();
virtual Base* clone() {
return new Foo();
}
};
Foo::~Foo()
{
}
int main()
{
Base* f = new Foo();
f->clone();
return 0;
}
using cmake, it is simply:
$ cat CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(bla)
add_library(test SHARED test.cpp)
add_executable(main main.cpp)
target_link_libraries(main test)
From linux:
$ export CXXFLAGS="-fvisibility=hidden -fvisibility-inlines-hidden"
$ cmake . && make
From windows:
$ cmake . -G"NMake Makefiles"
$ nmake
For people not using cmake, you could use:
$ cat Makefile
main: main.cpp test.h libtest.so
g++ -fvisibility=hidden -fvisibility-inlines-hidden -L. -ltest main.cpp -o main
libtest.so: test.cpp test.h
g++ -fvisibility=hidden -fvisibility-inlines-hidden -fPIC -shared test.cpp -o libtest.so
which leads to:
$ make
g++ -fvisibility=hidden -fvisibility-inlines-hidden -fPIC -shared test.cpp -o libtest.so
g++ -fvisibility=hidden -fvisibility-inlines-hidden -L. -ltest main.cpp -o main
/tmp/cc5lGsdn.o: In function `Base::Base()':
main.cpp:(.text._ZN4BaseC2Ev[_ZN4BaseC5Ev]+0xf): undefined reference to `vtable for Base'
/tmp/cc5lGsdn.o:(.rodata._ZTI3Foo[_ZTI3Foo]+0x10): undefined reference to `typeinfo for Base'
collect2: error: ld returned 1 exit status
make: *** [main] Error 1
In case this matter, adding -fno-devirtualize does not help (as per sug from here)

std::atomic library dependency (gcc 4.7.3)

I've been trying to compile with std::atomic, and I'm getting unresolved references to __atomic_load, __atomic_store, and __atomic_store_16.
I know in a later version of gcc (4.8+?) you include -latomic, but I'm compiling with gcc 4.7.3; I've tried adding -latomic_ops and -latomic_ops_gpl, but neither seem to do much.
I am installing gcc 4.8.1 now, but I do have a release platform that'll really need to be compiled for 4.7.3.
Many thanks.
Edit:
Ok, here's some code that results in the problem I have:
atomics.cpp
#include <atomic>
#include <stdint.h>
struct dataStruct {
int a;
uint16_t b;
float c;
dataStruct(int ai, uint16_t bi, float ci) noexcept : a(ai), b(bi), c(ci) {
}
dataStruct() noexcept : dataStruct(0,0,0) {
}
};
int main() {
std::atomic<dataStruct> atomicValue;
atomicValue = dataStruct(10, 0, 0);
return atomicValue.load().b;
}
With "g++-4.8.1 *.cpp -std=c++0x -latomic", this compiles fine.
With "g++-4.7.3 *.cpp -std=c++0x -pthread -lpthread -latomic_ops", it fails with the following:
/tmp/ccQp8MJ2.o: In function `std::atomic<dataStruct>::load(std::memory_order) const':
atomics.cpp:(.text._ZNKSt6atomicI10dataStructE4loadESt12memory_order[_ZNKSt6atomicI10dataStructE4loadESt12memory_order]+0x2f): undefined reference to `__atomic_load'
/tmp/ccQp8MJ2.o: In function `std::atomic<dataStruct>::store(dataStruct, std::memory_order)':
atomics.cpp:(.text._ZNSt6atomicI10dataStructE5storeES0_St12memory_order[_ZNSt6atomicI10dataStructE5storeES0_St12memory_order]+0x35): undefined reference to `__atomic_store'
collect2: error: ld returned 1 exit status
Ok, finally found the answer at: https://gcc.gnu.org/wiki/Atomic/GCCMM
Turns out, 4.7 did not in fact have 'official' atomics support (just the header files). If you want to use atomics in 4.7 compilers, you must download the source code linked on that page and build it yourself
gcc -c -o libatomic.o libatomic.c
ar rcs libatomic.a libatomic.o
Then, you can build it using
g++-4.7.3 -std=c++0x atomics.cpp -latomic -L./

Undefined reference to typeinfo when linking with nsRunnable

As firefox 12 sdk removed the 'Proxy' object, I wanted to use cross-thread calls using nsRunnable. I basically did copy-and paste of the code:
class NotifyTask : public nsRunnable
{
public:
NotifyTask(nsISupports *subject, const char *topic, bool remref)
: mWorkerThread(do_GetCurrentThread())
{
MOZ_ASSERT(!NS_IsMainThread()); // This should be running on the worker thread
}
NS_IMETHOD Run() {
MOZ_ASSERT(NS_IsMainThread()); // This method is supposed to run on the main thread!
mWorkerThread->Shutdown();
return NS_OK;
}
private:
nsCOMPtr<nsIThread> mWorkerThread;
};
And I tried to compile it. I got following errors:
g++ -std=gnu++0x -Wall -O2 -c -DUSE_LIBUSB -fPIC -DHAVE_CRYPTO -fpermissive -DCRYPTPP -fshort-wchar -I../../xulrunner-sdk/include -o gipsy.o gipsy.cpp
gipsy.cpp:74:7: warning: ‘NotifyTask’ declared with greater visibility than the type of its field ‘NotifyTask::<anonymous>’ [-Wattributes]
gipsy.cpp:74:7: warning: ‘NotifyTask’ declared with greater visibility than its base ‘nsRunnable’ [-Wattributes]
g++ -std=gnu++0x -Wl,-z,defs -Wall -Os -o gipsy.so -shared gipsy.o gipsymodule.o tracklog.o gpslib/data.o gpslib/garmin.o gpslib/gps.o gpslib/phys.o gpslib/igc.o gpslib/aircotec.o cp1250.o prefparser.o gpslib/foreignigc.o gpslib/mlr.o gpslib/flymaster.o gpslib/compeo.o gpslib/iq.o ../libs/libcryptopp.a -lusb -L../../xulrunner-sdk/lib -lxpcomglue_s -lxul -lxpcom -lplds4 -lplc4 -lnspr4 -lpthread -ldl -lmozalloc
gipsy.o:(.data.rel.ro._ZTI10NotifyTask[typeinfo for NotifyTask]+0x10): undefined reference to `typeinfo for nsRunnable'
collect2: ld returned 1 exit status
According to g++ undefined reference to typeinfo it might be that gecko sdk was built with -fvisibility=hidden and some weird 'key method in different .so'. Is this an error in Gecko sdk or am I doing something wrong?
The gecko SDK is not link with RTTI - adding "-fno-rtti" parameter to the particular .o file fixed the problem.