Difference between Unix and Linux for resolving symbols

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.

Thanks...

A binary built on HP (HP-UX?) will probably not run on a Linux box.

The executable will not run for sure.. as it is a C code.

The issue is that Linux is not able to build the executable for this and Unix is able to.

So, there is a difference between how Unix and Linux handle this scenario.

I am trying to understand that.

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.

I hope this helps.

bakunin

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

1 Like

Hi Shamrock,

I tried to use the -AC99 option in HP-Ux. the behaviour is same as cc. There was no error thrown.

In my initial attempts also, the executable was getting generated (which executable permission and I am able to run them).

And I used the term routine for the file.
So, I was calling test.c one routine and call1.c another. Sorry if I created confusion over there :slight_smile:

Thanks...

This shouldnt be happening...what is the version of your hpux box and also the C compiler you are using.

Can you post the output you are getting from that executable...

Alright makes sense...

the version is
(cc -V)

cpp.ansi: HP92453-01 B.11.11.20 HP C Preprocessor (ANSI)
ccom: HP92453-01 B.11.11.20 HP C Compiler

HPUx...

(uname -r)
B.11.23

which means it should be HP-UX 11i v2

the output being displayed is

./test

0

(as it is extern variable)

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

bakunin

You are right bakunin i got confused between routine and subroutine...:o

---------- Post updated at 01:24 PM ---------- Previous update was at 01:21 PM ----------

I think that the version of your C compiler is very old so you should get a new one or install gcc which is free of cost...

Can you post the output of "uname -a" on your hpux system...

here is what uname -a gives

HP-UX srv_name B.11.23 U 9000/800 srv_name unlimited-user license