Undefined Variable error - c

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

Related

How do I find out where main() is defined in a big project?

Let's say I have the following program (a.c):
#include <stdio.h>
void f()
{
printf("Hello, world!");
}
int main(void)
{
f();
return 0;
}
$ gcc -g a.c
Having a.out, how do I find out where main() is defined? I mean, in a big project it's not always clear where main() comes from.
You can use gdb. Probably there's a better command, anyway I know of:
$ gdb -batch -ex "info function main" a.out
All functions matching regular expression "main":
File a.c:
8: int main(void);
In the executable is not normally the place to look for a function definition. You can do the compiling of all source files and run nm(1) on them to see if any of them has a definition of main. The executable is not the proper place as it will have no reference to the module it came from. The source files will be hard to follow (as some can have compilation directives with optionally compiled code /with a main definition in case you don't provide one/ that will make uncertaing the place where you find it) but the compiled module will have a reference to main to indicate the linker it can get it and solve all the main references from this file. The linker divides a compiled input into a set of segments and piles them up to the appropiate places in the processor memory map, and so, you get a messed final executable with pieces of each module mixed up, making it more difficult to check if a main definition is there (it applies to main or to any other function)
Output should be something like:
0000000000000c10 T main
in the file that conttains it. In the opposite, all files that require main and need it provided by the linker appear as:
U memset
instead.

how to call a function located in another file in C using external?

I'm using a book, and now I'm studying external variables. I'm supposed to use a function located in another file and return a value from that function. But I don't understand how does this happens exactly. This is the code provided by the book:
This is the code in the first file:
#include <stdio.h>
double getCircum(double);
double PI = 3.14;
int gi;
int main(void)
{
double r = 5.87;
const double PI = 3.14;
printf("%.f", getCircum(r));
}
This is the code in the other file:
external double PI;
double getCircum(double r)
{
return 2 * r * PI;
}
The output is supposed to be 36.88. but I keep getting an error message that the file is not the directory. I don't know what file it that. Also, I don't really get how the code is supposed to look for a function in a different file, is the code missing something?
This is possible through to the linking process.
When reading your C first file, the compiler will output an object file which contain unresolved references to symbols like printf, getCircum because they are declared (printf in <stdio.h> and getCircum in your first file) but not implemented (you didn't wrote them code in the first file).
When reading the second file, the compiler will miss the definition of PI.
This doesn't prevent him from producing valid object files. After removing the line double PI = 3.14 (it miss a ;), compile without linking with :
cc -c -o 1st_file.o 1st_file.c
cc -c -o 2nd_file.o 2nd_file.c
This will output two object files, if you run obj-dump -t 1st_file.o 2st_file.o you will see a list of provided and unresolved symbols of both files.
Now we will link with cc -o program.exe 1st_file.o 2nd_file.o. The C compiler will link both objects and some system-wide ones inside program.exe.
And voilĂ  !
In your case cc -o program.exe 1st_file.c 2nd_file.c will do the job. But in real program, recompiling the whole program at each test take a lot of time, I have a private project which take 3,5 seconds to link vs 17,5 to recompile everything for 4k lines of code, Linux itself has more than a 2M lines of code...
Finally, post the console output and build command in the question, my answer make the important assumption that you are on a Linux with a working C compiler and GNU binutils, StackOverflow has a great doc here https://stackoverflow.com/help/how-to-ask to ask good question which have more chances to be solved
Edit: Defining PI 2 times here is not an error

MicroFocus cobol commands cobinit,cobcall and cobtidy are throwing errors in my C program

As per the documentation in Micro-focus support site, to call a cobol program from a C program we just need to follow the given below steps.
main(int argv, char *argv)
{
cobinit(); /* Initialize COBOL environment */
cobcall("cobep", 0, NULL); /* Call a COBOL program */
cobtidy(); /* Close down COBOL environment */
return(0);
}
Based on this I have come up with a simple C program to call an already working Cobol program, but guess I am getting linking error.
C Program
cat call.c
#include<stdio.h>
#include "cobcall.h"
#include "cobmain.h"
int main()
{
int ret=0;
cobinit();
ret=cobcall("cobolprogram.gnt",1,NULL);
cobtidy();
return 0;
}
Error message receiving
gcc -Wall call.c -o call
call.c: In function 'main':
call.c:10: warning: pointer targets in passing argument 1 of 'cobcall' differ in signedness
/usr/ccs/bin/ld: Unsatisfied symbols:
cobtidy (first referenced in /tmp/ccQBPw6r.o) (code)
cobcall (first referenced in /tmp/ccQBPw6r.o) (code)
cobinit (first referenced in /tmp/ccQBPw6r.o) (code)
collect2: ld returned 1 exit status
If you use MF then you likely have access to a paid support. In any case here's what I can tell you from knowing something about gcc and libraries.
The C compiler compiles fine. It only complains about signedness of a char * or const char *, but this shouldn't matter.
To solve this check in the header for the actual defintion of cobcall, I assume changing it to one of these should fix the compiler warning:
ret=cobcall((char *)"cobolprogram.gnt",1,NULL);
ret=cobcall((const char *)"cobolprogram.gnt",1,NULL);
ret=cobcall((unsigned char *)"cobolprogram.gnt",1,NULL);
ret=cobcall((const unsigned char *)"cobolprogram.gnt",1,NULL);
Side note: as far as I know you don't pass the file extension to cobcall, therefore to make it work later you may need to remove the .gnt part.
The errors you get are from the linker as it has no possibility to resolve these mf specific functions. I've skimmed over different MF docs but did not found the library name you need. Maybe it is libcob or libcobmf or libmfcob or ...
Edit: I've found a reference in an old MF manual naming the library libcobol.
As soon as you know the library name use -lname (for example -lcobol/ -lcob/ -lcobmf/-lmfcob) to let the linker know that it can resolve them in this library. Add -L/path/to/library to let the linker know where it can find the library.
If compilation worked any your main program complains about "cannot find libcob.so" (or libcobmf.so or whatever it is named) set LD_LIBRARY_PATH to point to the library name.

c compiler error with linking

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).

function header and implementation in different files C

How do you have a header file for a function and the implementation of that function in different files? Also, how do you have main in yet another file and call this function?
The advantage is so that this function will then be an independent component which can be reused, right?
This is best illustrated by an example.
Say we want a function to find the cube of an integer.
You would have the definition (implementation) in, say, cube.c
int cube( int x ) {
return x * x * x;
}
Then we'll put the function declaration in another file. By convention, this is done in a header file, cube.h in this case.
int cube( int x );
We can now call the function from somewhere else, driver.c for instance, by using the #include directive (which is part of the C preprocessor) .
#include "cube.h"
int main() {
int c = cube( 10 );
...
}
Finally, you'll need to compile each of your source files into an object file, and then link those to obtain an executable.
Using gcc, for instance
$ gcc -c cube.c #this produces a file named 'cube.o'
$ gcc -c driver.c #idem for 'driver.o'
$ gcc -o driver driver.c cube.c #produces your executable, 'driver'
Actually you can implement any function in header files for better performance(when implementing libraries for example) as long are not referenced to a specific object(actually it won't compile that).
By the way even with that way, you have separate interface and implementation ;)
Of course you will have include gurads in you header files to avoid "multiple definition" errors.
In C/C++, non-inline functions should be defined only once. If you put function defination
in header files, you will get "multiple defination" link error when the header file is included more than once.

Resources