Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

undefined reference to c functions in c++ code

Tags:

c++

linkage

I have a strange problem: the code bellow perfectly compiled.
src.cpp:

extern "C" {
    #include "header.h"
}

void A::Execute() {
    B::Instance().Reset(ix);
    c_func(ix);// this is c functions declared in header.h
    C::Instance().Erase(ix);
}

But when I comment out the c_funk() I get linkage error in all places where I use c functions from the header.h file.

With that minor change:

void A::Execute() {
    B::Instance().Reset(ix);
    //c_func(ix);// this is c function declared in header.h
    C::Instance().Erase(ix);
}

I get: undefined reference to c_func().
Any ideas how to solve it? Thanks.

Update:
I have added a dummy function to header.h: foo_for_linkage_problem();
and in such way solved the problem. As I understand the linker try to make some optimization that couses this problem. new code:

void A::Execute() {
    B::Instance().Reset(ix);
    foo_for_linkage_problem();// this is c empty function declared in header.h 
    C::Instance().Erase(ix);
}
like image 367
Todder Avatar asked Apr 15 '15 14:04

Todder


People also ask

What does undefined reference to a function mean c?

An “Undefined Reference” error occurs when we have a reference to object name (class, function, variable, etc.) in our program and the linker cannot find its definition when it tries to search for it in all the linked object files and libraries.

What is undefined reference to printf in c?

This error is often generated because you have typed the name of a function or variable incorrectly. For example, the following code: #include <stdio.h> void print_hello() { printf ("Hello!\n"); } /* To shorten example, not using argp */ int main() { Print_hello(); return 0; }

How do you resolve undefined references in C++?

You can fix undefined reference in C++ by investigating the linker error messages and then providing the missing definition for the given symbols. Note that not all linker errors are undefined references, and the same programmer error does not cause all undefined reference errors.

What is the meaning of undefined symbol in c?

UNDEFINED SYMBOL AT COMPILE TIME An undefined symbol at compile time indicates that the named identifier was used in the named source file, but had no definition in the source file.


1 Answers

tldnr: You have problem in the order the libraries are provided to linker.

I think that I know what is wrong. Let's assume that you have four files:

main.c:

#include <stdio.h>
    
int a();
int b();

int main()
{
    printf("%d\n", a());
    printf("%d\n", b());

    return 0;
}

main2.c:

#include <stdio.h>
    
int a();
int b();

int main()
{
    //printf("%d\n", a());
    printf("%d\n", b());

    return 0;
}

a.c:

int a()
{
    return 67;
}

b.c:

int a();

int b()
{
    return a()+5;
}

We create liba.a and libb.a:

gcc a.c -c -o a.o
gcc b.c -c -o b.o
ar rcs liba.a a.o
ar rcs libb.a b.o

Now we compile our exec:

gcc main.c liba.a libb.a -o test

And everything works just fine

gcc main2.c liba.a libb.a -o test

I get:

libb.a(b.o): In function `b':
b.c:(.text+0xa): undefined reference to `a'
collect2: error: ld returned 1 exit status

let's examine which symbols my libraries provides/requires:

$nm liba.a

a.o:
0000000000000000 T a

Symbol type T means that this library have file a.o which provides symbol a

$nm libb.a

b.o:
                 U a
0000000000000000 T b

libb.a contains file b.o which provides symbol b but requires symbol a

The linker does not include whole static library when asked. It looks which .o files are needed and links only those. Thus the order you provide the files is crucial.

When following command is executed, main.c gets compiled and it needs both a and b symbols. When linker gets liba.a library it links a.o file because it provides a symbol. When linker gets libb.a library it links b.o file because it provides b symbol. Everything works fine.

gcc main.c liba.a libb.a -o test

When the main2 command is executed, main2.c gets compiled and it needs only b symbols. When linker gets liba.a it does not link a.o becuase a is not needed at all. Then linker gets libb.a library it links b.o file because it provides b symbol. But the b.o file needs symbol a, and it is too late to link a.o, liba.a was already processed. Note that when I switch libraries it will compile cleanly:

gcc main2.c libb.a liba.a -o test
like image 80
luantkow Avatar answered Oct 05 '22 02:10

luantkow