undefined reference to a function c [duplicate] - c++

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 8 years ago.
This question maybe have been asked before. I could not find it to the best of my searches.
I'm trying to link libpfm4.5.0 in my code. The header file that I'm using is the following: perf_util.h
Here is the link to download libpfm4.5.0.
Does it matter where exactly I include the header file?
Here is a snippet of my code:
#include "matrix.h"
#include "perf_util.h"
int read_counts(int pid, int app_num){
int ret, i, num_fds = 0, grp, group_fd;
int ready[2], go[2];
char buf;
int nevents;
nevents = TOTAL_NUM_EVENTS;
go[0]=go[1] = -1;
for (grp = 0; grp < nevents; grp++) {
int ret;
ret = perf_setup_list_events(perf_events.pmc[grp], &fds_pid[app_num], &num_fds);
if (ret || !nevents)
exit(1);
}
}
the header file perf_util.h does contain perf_setup_list_events function but during compilation
matrix.o: In function `read_counts(int, int)':
matrix.c:(.text+0xf20): undefined reference to `perf_setup_list_events(char const*, perf_event_desc_t**, int*)'
collect2: error: ld returned 1 exit status
This is the error I get. What could be the possible places I would have done the error? Any help would be appreciated.
This is how I compile.
g++ -I. -I/libpfm-4.5.0/perf_examples/../include -DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -I. -D_GNU_SOURCE -pthread -w -c matrix.c
g++ -I. -I/libpfm-4.5.0/perf_examples/../include -DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -I. -D_GNU_SOURCE -pthread -w -o matrix matrix.o perf_util.o /libpfm-4.5.0/perf_examples/../lib/libpfm.a
Note: libpfm compiles using cc and I use g++. Could that be the problem? if yes, how should I solve it?
Here is how I compile it now:
cc -std=c99 -I. -I/libpfm-4.5.0/perf_examples/../include -DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -I. -D_GNU_SOURCE -pthread -w -c matrix.c
cc -std=c99 -I. -I/libpfm-4.5.0/perf_examples/../include -DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -I. -D_GNU_SOURCE -pthread -w -o matrix matrix.o perf_util.o libpfm-4.5.0/perf_examples/../lib/libpfm.a
error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘=’ token
const char * pmc[TOTAL_NUM_EVENTS] = {"blah", "blahbar"}
I've a const char * array and this is the error I get.

OK, so, contrary to what I thought at first, your program is a C++ program. We know this is the case because the C++ compiler accepts it and the C compiler doesn't. (You still haven't given enough information for me to understand why the C compiler doesn't like it, but I suspect it's something uninteresting like defining a file-scope variable that can't be fully initialized at compile time. If you meant this to be a C program you should ask a new question about that. Anyway.)
The library you are using is C, not C++, and its header files are not set up to be used from C++ programs. I deduced that this was the problem from the error message:
undefined reference to `perf_setup_list_events(char const*, perf_event_desc_t**, int*)'
See how that error message gives a full prototype for the function perf_setup_list_events? That's because C++ has function overloading and C doesn't -- so, in C++, every function is given a "mangled name" which encodes its prototype. If you do nm matrix.o | grep perf_setup_list_events you will discover this mangled name: it's probably something like _Z22perf_setup_list_eventsPKcPP17perf_event_desc_tPi. The linker is helpfully decoding that again to a prototype.
So, the fact that the linker error has a full prototype, all by itself, tells me that the undefined reference is from code compiled as C++. Now, I have never heard of libpfm4.5.0 before, but I do know that you would have gotten a different error message if your library didn't actually define that function -- something like
error: ‘perf_setup_list_events’ was not declared in this scope
So I guessed that the library is written in C, not C++, and that its header files are not written to handle being used from C++ programs. This is a defect in the library, but one that can be worked around by writing
extern "C" {
#include "perf_util.h"
}
instead of just the bare #include. The extern "C" { ... } construct tells a C++ compiler to not apply name mangling to whatever is declared within. Thus, your program, when compiled that way, looks for a symbol named perf_setup_list_events instead of _Z22perf_setup_list_eventsPKcPP17perf_event_desc_tPi and it links successfully.

Related

CS50 - C++: issue with " using namespace std;" [duplicate]

There's a C++ code:
#include <stdio.h>
int main() {
int b = sizeof('a');
if(b==4) printf("I'm a C program!\n");
else printf("I'm a C++ program!\n");
}
Compile it like this:
gcc main.cpp -o main
It succeeds and gives:
I'm a C++ program!
Then add a line somewhere inside function main
int *p1 = new int [1000];
It fails with:
C:\Users\...\AppData\Local\Temp\cccJZ8kN.o:main1.cpp:(.text+0x1f): undefined reference to operator new[](unsigned long long)'
collect2.exe: error: ld returned 1 exit status
Then the following two commands successfully compile the code:
gcc main.cpp -o main -lstdc++
and
g++ main.cpp -o main
The compiler is minGW-win64 (http://mingw-w64.sourceforge.net/).
The questions are:
Which of the two last commands are better?
To my mind gcc correctly chooses the right compiler but then uses a wrong linker. Is it right?
May it be a problem in minGW-win64?
As I see (correct me if it's wrong) gcc was intended to be a main program that takes the input and decides what to do with it. So I'd better use gcc if it worked without -lstdc++. But if it's not possible I'll prefer using g++ instead as don't know what else gcc may miss.
Many thanks for your considerations
gcc is the GCC compiler-driver for C programs, g++ is the one for C++ programs.
Both will guess the language on the basis of the file-extension, unless overridden.
But if you use the wrong driver, the default-options will be wrong, like leaving out the C++ standard-library for C++ programs compiled with gcc when linking.
You can add just the library with -lstdc++, though using the proper driver is preferable, as plain gcc may be missing other, subtler options.

C/C++ linking issue with a very simple setup [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 5 years ago.
I'm getting an "undefined reference" error when trying to compile and link a very simple app that has a dependency on a third-party library.
My main.c looks like this:
#include "ss7cp.h"
/*
extern "C" {
void EINSS7CpMain_CpInit(void);
}
*/
int main() {
EINSS7CpMain_CpInit();
}
The third-party header file has:
#if defined (__cplusplus) || defined (c_plusplus)
extern "C" {
#endif
...
void EINSS7CpMain_CpInit(void);
The definition of this function is in an archive:
$ nm -g /path/to/lib/libsign_64_uthr.a | grep EINSS7CpMain_CpInit
0000000000005ae0 T EINSS7CpMain_CpInit
U EINSS7CpMain_CpInit
U EINSS7CpMain_CpInit
By the "T" above, the function must be defined in the text/code section of one of the libs in the archive.
I'm currently not using a Makefile, but just trying to quickly build this simple app entirely from the command line:
g++ -I/path/to/include -L/path/to/lib -lsign_64_uthr -D__EXTENSIONS__ -DLINUX main.c
(The documentation told me to define both __EXTENSIONS__ and LINUX). The rest of the above is pretty straightforward. What I'm getting is:
/tmp/ccvgmIJ8.o: In function `main':
main.c:(.text+0x5): undefined reference to `EINSS7CpMain_CpInit'
collect2: error: ld returned 1 exit status
I've tried both as a C file (main.c) and C++ file (main.cpp, enabling the extern "C" block), but no difference. (Can I assume g++ decides on C versus C++ just by the file extension?)
I've even just compiled the file (with -c) and took a look at the contents of the resultant main.o object file and saw the text "EINSS7CpMain_CpInit" as it is, unmangled (or maybe that's just a debug symbol?)
What are some diagnostics steps I can take to see what I'm missing? Do I actually need to create a Makefile and split the compile and link steps?
It's been ages since I last did any C/C++ and even back when I did it, I usually wasn't the one who had to create the Makefiles from scratch, so I'm probably missing some very fundamental stuff here...
My best guess would be parameter ordering, the lib should come after the source file:
g++ -I/path/to/include -D__EXTENSIONS__ -DLINUX main.c -L/path/to/lib -lsign_64_uthr

undefined reference error for g++ but not for gcc when using BSP library

I am making a parallel program for one of my courses. Now initially it was written in C and it all worked just fine. Then we changed it all to c++ and all of a sudden I get some error when I try to compile the program. I am using the package mcbsp (Multicore BSP) for the parallel part. Here is the program
#include <stdio.h>
#include <stdlib.h>
#include <mcbsp.h>
void sieve(){
return ;
}
main(int argc, int **arhv){
bsp_begin(5);
printf("%d\n",bsp_pid());
bsp_end();
return 0;
}
So I make a file aaa.c and aaa.cpp both with this content. Then when I type in the terminal
gcc aaa.c -MMD -g -I../bsp/include -L../bsp/lib -lmcbsp1.2.0 -lpthread
it compiles just fine and the program does as expected (print the id of the cores). However, when I type
g++ aaa.cpp -MMD -g -I../bsp/include -L../bsp/lib -lmcbsp1.2.0 -lpthread
it gives the following feedback
/tmp/ccH3uox9.o: In function `main':
/home/teun/Documents/C/BSP/Sieve/sieve/aaa.cpp:10: undefined reference to `bsp_begin(unsigned int)'
/home/teun/Documents/C/BSP/Sieve/sieve/aaa.cpp:11: undefined reference to `bsp_pid()'
/home/teun/Documents/C/BSP/Sieve/sieve/aaa.cpp:12: undefined reference to `bsp_end()'
collect2: error: ld returned 1 exit status
I have been stuck with this for about an hour now and it is really getting frustrating. I must admit that I have little experience in programming in c++ as I mostly use C. Does anyone know what is going wrong?
EDIT: The program I displayed is just a small working example that uses the BSP functionality.
The simple declaration int bsp_end(); is interpreted differently in C and C++. The reason is that in C++, you can overload functions, which requires that their parameters are included in the symbol name for the linker, see C++ name mangling for further info. Now, since the function is compiled with a C compiler but the declaration is given to a C++ compiler, the symbols don't match and you get linker errors.
As a solution, add extern "C" to the function declaration or maybe wrap the whole include:
extern "C" {
#include <mcbsp.h>
}
You need extern "C" around #include
extern " C" {
#include "c-header.h"
};
This is needed to stop the C++ name mangling

Using c library in c++ code with makefile

I have a C library made by cluster.h and cluster.c. I compiled that with gcc -c cluster.c.
I have to use a method of this library in the main class of a C++ project. This is the makefile i use:
abundancebin: main.o profileManager.o myHash.o myMalloc.o myStack.o myStringHash.o
g++ -o abundancebin main.o profileManager.o myHash.o myMalloc.o myStack.o myStringHash.o
main.o: main.cpp
g++ -c main.cpp
profileManager.o: profileManager.cpp
g++ -c profileManager.cpp
myHash.o: myHash.cpp
g++ -c myHash.cpp
myMalloc.o: myMalloc.cpp
g++ -c myMalloc.cpp
myStack.o: myStack.cpp
g++ -c myStack.cpp
myStringHash.o: myStringHash.cpp
g++ -c myStringHash.cpp
clean:
-rm *.o abundancebin
I tried to import the C library in main.cpp using after other imports:
#ifdef __cplusplus
extern "C" {
#endif
#include <cluster.h>
#ifdef __cplusplus
}
#endif
but when i compile with make i have this response:
main.cpp:29:21: fatal error: cluster.h: No such file or directory
#include <cluster.h>
^
compilation terminated.
make: *** [main.o] Error 1
if i use "cluster.h" instead of i have this error:
main.o:main.cpp:(.text+0xf68): riferimento non definito a "kmedoids"
main.o:main.cpp:(.text+0xf68): rilocazione adattata per troncamento: R_X86_64_PC32 contro il simbolo non definito "kmedoids"
/usr/bin/ld: main.o: bad reloc address 0x18 in section.xdata'
collect2: error: ld returned 1 exit status
make: * [abundancebin] Error 1`
I also tried to copy the code part i need from C library to C++ project but the compiler reports many errors like this:
error: invalid conversion from ‘void*’ to ‘int*’ [-fpermissive]
vector = malloc(nnodes*sizeof(int));
The library files are in the same folder of the project files. Can someone help?
Thank you
If you want to add some code which is wrote in c language, you have to #include it like:
extern "C" {
#include "x264.h"
}
which tell compiler to deal with it differently, and its not necessary to change your code to c++
1: you add your code as: #include <cluster.h>
its better to change it to: #include "cluster.h"
the different is, the second one tell the compiler to first search for your header in the current directory and then in the main c++ libraries directory
your error:
main.cpp:29:21: fatal error: cluster.h: No such file or directory
is because it can't find the header, so, if cluster.h is in the same directory as main.cpp, use #include "cluster.h"
or you can use -I. (which tell its in the current directory) or -I/address to tell compiler where to look for your header
when you correct it, you get the second error, which I believe its because of your code, and I think its because of your code in main.cpp, and do not have anything with your cluster code, I suggest, try to post your code to find out what's the problem
In answer to your question, I would approach it something like this in the makefile:
all: cfile.o
g++ main.cpp -o app
cfile.o: cluster.c cluster.h
gcc -c cluster.c
Note: This assumes that everything is in the same directory, so take care to specify paths if not.
Let me know of any further errors.

Linking problems with g++, but not with cc [duplicate]

This question already has answers here:
How to resolve the linker error in C++ compiler
(3 answers)
Closed 9 years ago.
I'm using 64-bit CentOS version of Linux. I'm trying to create and use a static library (libUtility.a) in my C and C++ programs. I can compile the library with C, and produce the libUtility.a file with ar. Then I try to link it into my program. Everything works when I use the C compiler
cc myprog.c -o myprog -I/usr/local/include -L/LocationOfMyLib -lUtility
However, when I use the g++ compiler, I receive the errors.
g++ myprog.c -o myprog -I/usr/local/include -L/LocationOfMyLib -lUtility
myprog.c: In function 'int main(int, char**)':
/tmp/cckIN1Yk.o: In function `main':
myprog.c:(.text+0x41): undefined reference to `Utility_HiWorld(char*)'
collect2: ld returned 1 exit status
I have moderate experience in C and C++, but no experience creating my own
libraries. This library only has one subroutine named Utility_HiWorld(). And myprog.c only calls that one subroutine. What am I doing wrong in here?
NEW: Okay, I definitely didn't use 'extern "C"'. I didn't even know what that was. That solved it.
I would guess that you are failed to tell your C++ compiler that the external function is written in C.
Since you want to use the library from C and C++ you need to do something like this in your libraries header file.
#ifdef __cplusplus
extern "C" {
#endif
void Utility_HiWorld(char*);
#ifdef __cplusplus
}
#endif
__cplusplus is only defined for a C++ programs, so a C++ program will see extern "C" { ... } which is what it needs to tell it that Utility_HiWorld is a C function.
See here for more details.
Just a guess, post some code if you think the problem is something else.