c compiler error with linking - c

Here is the error I get from the gcc call:
gcc -o rr4 shells2.c graph1.c rng.c;
Undefined symbols:
"_getdisc", referenced from:
_main in cckR7zjP.o
ld: symbol(s) not found
The "cckR7zjP.o" keeps changing every time I call the compiler. The code for the method is in the file graph1.c; its header file is called graph2.h, and I am importing it to the file with the main method called shells2.c using:
#include "graph2.h"
The method or function definition is:
int getdisc(int i){ return disc[i];}
which attempts to return the ith member of the array disc created by
static int *disc;
that I already initialized in some other method! I think the problematic call is:
for (iter = 0; iter < n; iter++) {
if (getdisc(iter) == cln)
avgbtwn += get_betweenness(iter);
}
This seems like a linker problem I checked with some other questions, and I think I am linking my method properly (and am using the same method elsewhere in the code) but I still can't figure this out.
Edit: So I switched the order of the command in linux to
gcc -o rr4 graph1.c rng.c shells2.c
as per Soren's suggestion and the function compiled as normal, does anyone know why?
Further it seems when i put a trailing line break in the file graph1.c alleviates the problem.

There used to be a issue in the old GCC 2.x compilers/linkers where the linker couldn't resolve linking when the symbols were not group together -- think of it as that the linker would only looks for symbols that is still needed, and it would drop symbols which were unused.
To most people the problem would manifest itself as a problem of the ordering of libraries (specified with -l or as .a).
I see from the comments that you use a mac, so it might just be that the mac version of the compiler/linker still has that problem -- anyway since reordering the source files solved the problem, then you certainly have some variation of this bug.
So possible solutions;
Group all your source files into larger files -- bad solution -- but the linker is less likely to fail with this symptom -- or
Try to compiler all the files to .o first and then link the .o files (using a makefile would usually do this, but may or may not resolve the problem) and possibly combine the .o into a single .a (man ar), or
Change the order of the source files to have the shells2.c last (which worked for you), or
See if upgrading your compiler helps
Sorry for the long laundry list, but this is clearly just a compiler bug which just need a simple work around.

That's definitely an error with getdisc not being visible to the linker but, if what you say is correct, that shouldn't happen.
The gcc command line you have includes graph1.c which you assure use contains the function.
Don't worry about the object file name, that's just a temprary name created by the compiler to pass to the linker.
Can you confirm (exact cut and paste) the gcc command line you're using, and show us the function definition with some context around it?
In addition, make sure that graph1.c is being compiled as expected by inserting immediately before the getdisc function, the following line:
xyzzy plugh twisty;
If your function is being seen by the compiler, that should cause an error first. It may be something like ifdef statements causing your code not to be compiled.
By way of testing, the following transcript shows that what you are trying to do works just fine:
pax> cat shells2.c
#include "graph2.h"
int main (void) {
int x = getdisc ();
return x;
}
pax> cat graph2.h
int getdisc (void);
pax> cat graph1.c
int getdisc (void) {
return 42;
}
pax> gcc -o rr4 shells2.c graph1.c
pax> ./rr4
pax> echo $?
42
We have to therefore assume that what you're actually doing is something different, and that's unusually tactful for me :-)
What you're experiencing is what would happen with something like:
pax> gcc -o rr4 shells2.c
/tmp/ccb4ZOpG.o: In function `main':
shells2.c:(.text+0xa): undefined reference to `getdisc'
collect2: ld returned 1 exit status
or if getdisc was not declared correctly in graph1.c.
That last case could be for many reasons including, but not limited to:
mis-spelling of getdisc.
#ifdef type statements meaning the definition is never seen (though you seem to have discounted that in a comment).
some wag using #define to change getdisc to something else (unlikely, but possible).

Related

Compiler does not give line number of error undefined reference

Why does the compiler sometimes not give line number of the error? Where is the use case of that "undefined reference". I've already included everything as header files I myself wrote so it needs to give a specific line number. It is not closed source. Have I changed some setting of the compiler by accident or is it another thing whatever that another thing is?
D:\Projects\DanceOfPixels\GLEW>gcc main.c glad.c -IC:\mingw_dev_lib\include\SDL2 -LC:\mingw_dev_lib\lib -lmingw32 -lopengl32 -lSDL2main -lSDL2 -lSDL2_image -o main.exe -ansi -std=c89 -pedantic -w
C:\Users\user\AppData\Local\Temp\ccMooHZm.o:main.c:(.text+0x126ce): undefined reference to `drawImagePartScaledHW'
collect2.exe: error: ld returned 1 exit status
Edit: I have solved the problem. I have included two different versions of the draw.h, one coming from software renderer, other from OpenGL renderer. Since they use same
#ifndef DRAW_H
#define DRAW_H
...
#endif
structure for both files; the compiler didn't include the second. Once I've changed the DRAW_H to DRAW_HW I managed to compile and run the application.
That error comes from the "linker" (ld), not the compiler proper.
Typically, the compiler compiles each source file into its own, individual object file, containing just the code and data from that source file. Then, the linker combines one or more object files together, and also links in any needed library functions.
Crucially, there's no problem if a single source file (a single object file) calls an undefined function -- that's normal, if the definition of the function is in another source file, or a library. So that's why it's the linker (not the compiler) that finally discovers that there's not a definition for a function anywhere, that it's truly undefined.
But since the linker is working with object files, typically it doesn't know which source file line numbers the functions were originally called on.
(Some C compilers work more closely with their linkers, so that these "undefined external" error messages can, more usefully, contain actual source file line numbers, but that's a relatively recent innovation. For this to work it may be important to compile with debugging enabled, e.g. by using the -g flag, so that the compiler includes source line number information in its object files.)

C - Very Strange Implicit Declaration

I had a function in a file "draw.h":
void TileSystem() {
// Some code here.
}
And in the "main.c" file, I call it, because I have #included "draw.h" in the file. The function works nicely well!!
But then, I decide to rename the function to
void CreateTileSystem() {
// Some code here.
}
And I get the following output:
gcc main.c -std=c99 -o main `pkg-config --cflags --libs allegro-5.0 allegro_acodec-5.0 allegro_audio-5.0 allegro_color-5.0 allegro_dialog-5.0 allegro_font-5.0 allegro_image-5.0 allegro_main-5.0 allegro_memfile-5.0 allegro_physfs-5.0 allegro_primitives-5.0 allegro_ttf-5.0`
main.c: In function ‘main’:
main.c:217:12: warning: implicit declaration of function ‘CreateTileSystem’ [-Wimplicit-function-declaration]
/tmp/cclNEg6q.o: In function `main':
main.c:(.text+0xb1e): undefined reference to `CreateTileSystem'
collect2: error: ld returned 1 exit status
make: *** [main] Error 1
And then, I just rename it back to TileSystem and works well. I have no other references in the entire code. It makes no sense at all! I want to rename, in order to use verbs in functions (A more "correct" standard, I think). Well, I would really like to know what happens. I really CAN'T find errors, and the fact that when I rename it, it backs to work, frustrates me even more.
Thank you very much!
You have to also change the name in the header file, draw.h.
That error/warning indicates that there was no forward declaration for the function, which in older C dialects results in an assumption that the function is int fn(int) (if memory serves).
It works when you change it back because the header was never modified, so it's still providing a forward declaration of the old name.
I tried creating a couple of simple files like you've described here, but I don't get any problems. So:
are you sure you used the same name for the new function in both draw.h and main.c (really sure)?
I don't know about allegro: does it happen to have a function called TileSystem in it?
Beyond those, I would recommend starting with a bare bones setup (so just the include, the main function, and the call in main.c, and just the declaration in draw.h), make sure that compiles with gcc main.c -std=c99 -o main, and then build your application up to what it is currently, piece by piece, until the error starts happening again. That should help you identify the source of the problem.
I recreated the header file, without altering anything, and it worked. It really had something to do with me never altering the file (I mean, renaming the file or excluding it). Some very underground compiling issue happened.

Undefined Variable error

I'm a newbie to programming in C, and I'm having trouble understanding the error that is coming up when I attempt to compile my program. I've got the following program, which is fairly simple and which my professor says is correct:
#include <stdio.h>
#define TRUE 1
#define FALSE 0
#define BOOL int
extern int x;
extern BOOL do_exp;
int exp_or_log();
main()
{
x = 10;
do_exp = TRUE;
printf("2^%d = %d\n", x, exp_or_log()); //should print 1024
x = 145;
do_exp = FALSE;
printf("log(%d) = %d\n", x, exp_or_log()); //should print 7
}
But when I try to compile it, I get:
"_x", referenced from:
_x$non_lazy_ptr in ccWdLlxk.o
"_exp_or_log", referenced from:
_main in ccWdLlxk.o
_main in ccWdLlxk.o
"_do_exp", referenced from:
_do_exp$non_lazy_ptr in ccWdLlxk.o
ld: symbol(s) not found
I don't even have enough of an idea of what that means to know where to begin trying to figure out the problem. If anyone has a helpful explanation, or even just a general idea of what I should look at to begin problem shooting, I'd really appreciate it.
x, do_exp, and exp_or_log() are all defined in another file, I'm guessing supplied by your professor. You need to link together with that file. This is usually done by adding its filename along with yours on your compile line.
You've declared to the compiler that these variables and functions are available, but not necessarily defined in this particular source file:
extern int x;
extern BOOL do_exp;
int exp_or_log();
And they are not defined in that source file. However, the linker needs to be able to resolve those names, and the error message you're getting indicates that the linker can't find those names in any of its input files.
You need to wither provide the linker (ld) with a library that has these things, or you need a C file that defines them, and ahave that C file also compiled and linked in.
It's not the compiler that is complaining:
ld: symbol(s) not found
The linker (ld) cannot find the referenced symbols. You haven't provided their definitions.
First, note how you used the extern keyword on two variable definitions.
extern int x;
extern BOOL do_exp;
This means:
These variable are created elsewhere
(extern ally). You should be aware
that they exist, but they exist
somewhere else.
If these variable are intentionally declared in another file, you need to link compile that other file with yours, and link them together.
However, I suspect it is more likely that you just meant to declare them.
int x;
BOOL do_exp;
Report back on this, then we'll begin dealing with your function exp_or_log.
I'm guessing you're using a *nix machine from the output, so you would need to:
cc -c Anna_program.c
This should produce Anna_program.o. In your error the gibberish .o file was the same as this one, but was temporary, so was given a psudo-random name. The -c flag has the effect of only compiling the source file, and leaves off linking, which produces the executable, for later.
Then you can do:
cc Anna_program.o other_file.o -o Anna_program
And produce the executable Anna_program. If you aren't using a *nix style compiler then your sets will be different and you may need to put an extension on the end of the output file name in the last command.
You could do:
cc Anna_program.c other_file.o -o Anna_program
Which would combine the previous two steps.
What you should remember is that cc (or gcc) aren't actually the compiler, but a simple compilation manager. Under the hood they run other programs which do different steps in building your programs. By default cc will try to take what you give it and produce an executable (a.out), running as many of the steps as needed based on what you have given it. You can pass it flags, such as -c to tell it to only go part way (compiling and assembling, in this case).
The steps for C are Preprocessing (done by the program cpp), compiling (done by cc1), assembling (done by as), and linking (done by ld).
The cc or gcc command decides what needs to be done and then runs these other programs to do it.
You're having linker problems.
See the top of your code:
extern int x;
extern BOOL do_exp;
int exp_or_log();
Those three lines are like promises to the compiler. You're saying, trust me, when the time comes you'll be able to find an integer x, a BOOL do_exp, and a function exp_or_log();
The extern makes this promise for variables and the fact that the function doesn't have a body: {...} makes it for the function.
The linker is complaining because you're not following through on your promise. You need an implementation of exp_or_log(), and to have declared x and do_exp.
Is there more code? If you make another file, call is x.h, with the following content:
int x;
int do_exp;
int exp_or_log() {
return 6;
}
and then include this in your .c file:
#include "x.h"
You'll get some output. In this case it's nonsensical but it will compile while you fix the logic problems.
$ ./a.out
2^10 = 6
log(145) = 6

how do I always include symbols from a static library?

Suppose I have a static library libx.a. How to I make some symbols (not all) from this library to be always present in any binary I link with my library? Reason is that I need these symbols to be available via dlopen+dlsym. I'm aware of --whole-archive linker switch, but it forces all object files from library archive to linked into resulting binary, and that is not what I want...
Observations so far (CentOS 5.4, 32bit) (upd: this paragraph is wrong; I could not reproduce this behaviour)
ld main.o libx.a
will happily strip all non-referenced symbols, while
ld main.o -L. -lx
will link whole library in. I guess this depends on version of binutils used, however, and newer linkers will be able to cherry-pick individual objects from a static library.
Another question is how can I achieve the same effect under Windows?
Thanks in advance. Any hints will be greatly appreciated.
Imagine you have a project which consists of the following three C files in the same folder;
// ---- jam.h
int jam_badger(int);
// ---- jam.c
#include "jam.h"
int jam_badger(int a)
{
return a + 1;
}
// ---- main.c
#include "jam.h"
int main()
{
return jam_badger(2);
}
And you build it with a boost-build bjam file like this;
lib jam : jam.c <link>static ;
lib jam_badger : jam ;
exe demo : jam_badger main.c ;
You will get an error like this.
undefined reference to `jam_badger'
(I have used bjam here because the file is easier to read, but you could use anything you want)
Removing the 'static' produces a working binary, as does adding static to the other library, or just using the one library (rather than the silly wrapping on inside the other)
The reason this happens is because ld is clever enough to only select the parts of the archive which are actually used, which in this case is none of them.
The solution is to surround the static archives with -Wl,--whole-archive and -Wl,--no-whole-archive, like so;
g++ -o "libjam_candle_badger.so" -Wl,--whole-archive libjam_badger.a Wl,--no-whole-archive
Not quite sure how to get boost-build to do this for you, but you get the idea.
First things first: ld main.o libx.a does not build a valid executable. In general, you should never use ld to link anything directly; always use proper compiler driver (gcc in this case) instead.
Also, "ld main.o libx.a" and "ld main.o -L. -lx" should be exactly equivalent. I am very doubtful you actually got different results from these two commands.
Now to answer your question: if you want foo, bar and baz to be exported from your a.out, do this:
gcc -Wl,-u,foo,-u,bar,-u,baz main.o -L. -lx -rdynamic
Update:
your statement: "symbols I want to include are used by library internally only" doesn't make much sense: if the symbols are internal to the library, why do you want to export them? And if something else uses them (via dlsym), then they are not internal to the library -- they are part of the library public API.
You should clarify your question and explain what you really are trying to achieve. Providing sample code will not hurt either.
I would start with splitting off those symbols you always need into a seperate library, retaining only the optional ones in libx.a.
Take an address of the symbol you need to include.
If gcc's optimiser anyway eliminates it, do something with this address - should be enough.

Errors while compiling Neko VM OS X

I'm trying to compile the Neko VM on Mac OS X (10.5.7) using GCC 4.01 and I'm completely stuck, because it stops while compiling saying:
vm/threads.c:202: error: conflicting types for 'neko_thread_register'
vm/neko_vm.h:37: error: previous declaration of 'neko_thread_register' was here
I've tried googling this and some say it's because of lack of a "prototype" and some say it's because of a header include being done several times, and I can't really find any of those.
The affected line in threads.c:202 looks like this:
EXTERN bool neko_thread_register( bool t ) {
And the affected line in neko_vm.h:37 looks like this:
EXTERN bool neko_thread_register( bool t );
I can't see any difference in them, besides one of them being the implementation of the other.
The compiler command I'm using is:
cc -Wall -O3 -v -fPIC -fomit-frame-pointer -I vm -D_GNU_SOURCE -arch i386 -L/usr/local/lib -L/opt/local/lib -I/opt/local/include -o vm/threads.o -c vm/threads.c
I'd appreciate some ideas on what i might be able to do here, I don't really know where to go from here.
A mirror of the code for Neko which I'm trying to compile can be found here.
Thanks!
Have you tried compiling that file alone and outputting the preprocessed version? It could be that the scope or linkage macros are being modified somewhere in between the header file and the implementation file-- the same could be true of the 'bool' type, which is usually a macro defined by a system header.
According to the GCC 4.2 docs here, you should need to add the -E flag to the compilation line above, and you ought to change -o vm/threads.o to -o vm/threads.i so a file with the correct extension is created (.i means 'preprocessed file', essentially).
First, make sure you compile this as C, not C++.
Second, without seeing the code, it's pretty much impossible to say what the problem is.
But reading the error messages is often helpful (even before you google them):
Apparently neko_thread_register is declared twice, once in threads.c:202 and once in neko_vm.h:37, and the two declarations have different (conflicting) types. So look at the two declarations. If you can't see a problem with them, show us some code.
At the very least, seeing those two lines of code would be necessary. Most likely, the types are typedefs or macros or something similar, and then we'd need to see where they are defined as well.
Without seeing the code, all we can do is repeat the compiler error. "neko_thread_register has two conflicting definitions, at the lines specified."
Did you uncomment this line:
# For OSX
#
# MACOSX = 1 <-- this one
In the makefile?

Resources