I came across a difference between Unix and Linux, when it comes to resolving the symbols from the libs.
consider the following code segments...
$ cat call1.c
#include <stdio.h>
int a1;
extern int a3;
void prnt_a3()
{
printf("\n%d\n",a3);
}
$ cat test.c
#include <stdio.h>
extern int a1;
int main()
{
int a2=20;
printf("\n%d\n",a1);
return 0;
}
Highlights are...
a1 is defined in call1 and is being referenced in test.c and is being used also
a3 is referenced to in test.c and is not defined anywhere. It is being used but in a dead function prnt_a3
I am running it as
cc -g -c test.c call1.c
ar q lib.a call1.o
cc -g -o test test.o lib.a
The executable gets build in HP Unix bit in Linux, it fails saying
call1.c:6: undefined reference to `a3'
collect2: ld returned 1 exit status
I don't know the concept/rationale behind the same. :wall:
HPUx just refers to the data definitions and it doesn't bother about the functions unless there is atleast 1 function being used from that routine (in which case, HP also gives error) ???
If anyone can suggest some reading material for the same, it'll also be great.
First off, it has often been said and i will say it again: "Unix" is not an operating system, but a trademark. A system is "Unix", because its manufacturer bought the license to bear this trademark. "Linux" (to be precise: its manufacturers) did not purchase anything (mostly because there is no money to do so involved in Linux) and this is the only reason "Linux" is not a "Unix", but only "unixlike". This is about the same difference as "sparkling wine" versus "champagne": there is none. "Champagne" is the sparkling wine produced in the french area called Champagne, but that's it. You could create a sparkling wine which is absolutely identical to champagne - you would still not be allowed to call it "champagne" it you don't do so in the Champagne (and probably meet some other legalities too), but that would be about it.
The only real standard of any value is the POSIX standard. Linux is in most regards, AFAIK, compatible against this OS blueprint and so is HP-Ux (to which extent they actually conform i don't know - it is not the point of the argument).
Having said this: the real difference you perceive in your example above is probably the difference in the respective compiler suits. Try "gcc" in both environments (i suppose the HP-Ux compiler is not available in a Linux version) and probably the differences will vanish.
No there is no difference between the way unix and linux resolve symbols...the thing you are seeing is the default compilation mode in hpux is c89 while in linux it is c99 which is far more stricter than c89. In fact you will get the same error if you switch the default compilation mode in hpux to c99 by adding the following switch to your command line...
cc -AC99 <blah blah blah>
prnt_a3 is not a dead function...it is very much live and it is supposed to print an unallocated and undefined variable a3 which is an error...there is no difference in its treatment when it comes to unix or linux...
Even thogh hpux generates an a.out file yet that file isnt executable...did you even try to run the a.out file produced from the compilation...on my hpux box it says it cannot execute which is true as the compilation wasnt complete and so a load module wasnt generated. Linux is somewhat smarter and gives a linker error and stops there.
Isnt function and routine the same thing so state your problem clearly...
"extern" means "don't allocate any memory for this variable -- assume it already exists". Except it doesn't -- you've never actually defined it anywhere -- so the assumption ends up being wrong. When the linker looks for it, it can't find it.
HP's linker really ought to complain, too. A linker's not supposed to just invent nonexistent variables for you. I can imagine that causing really weird bugs someday.
Here's how it's supposed to work:
$ cat myextern.c
#include "myextern.h"
// This actually defines the contents of the variable.
// This is what actually makes the variable exist.
int myextern=3;
$ cat myextern.h
#ifndef __MYEXTERN_H__
#define __MYEXTERN_H__
extern int myextern;
#endif/*__MYEXTERN_H__*/
$ cat uses-extern.c
#include <stdio.h>
#include "myextern.h"
int main(void)
{
printf("myextern = %d\n", myextern);
return(0);
}
$
I totally agree that what I am trying to do in the code in HPUx is completely illogical.
That's why I was expecting the error during the executable formation in HPUx also.
But I was surprised by what actually happened over there.
So I was just wondering if there is any difference in the handling for symbols in both linkers or possibly just a loose checking (/bug) on HPUx side.
Actually, according to Niklas Wirth, it isn't: "routine" is a collective term for "procedures" and "functions". "Function" being a routine with exactly one return value, whereas "procedure" is a routine with no return value at all.
C blurs this difference by treating everything as a function, but PASCAL and similar languages don't. The closest analogon to a "procedure" in C would be a function defined to return "void".