Extern global variable and shared library.

Hans van Leeuwen hvleeuwen@baan.nl
Mon Oct 8 04:50:00 GMT 2001


Hi,

Please consider the next situation.

A C program contains a "extern global variable". A function in a shared
library contains the same variable but not extern.
On Linux (2.4.6) and SUN (5.6) both are separate variables. On HP (11.00),
IBM (AIX 4.3.3) and DIGITAL (V4.0) these are the same variable.
The shared library is linked with -Bsymbolic because a sub-function of a
shared library function must be taken from the shared library and not from
the source with the main function.

$ cat Makefile
  FLAG=-Bsymbolic
  #FLAG=

  mainf:		mainf.o libsubf.so
  	cc -g mainf.o -L. -lsubf -o mainf

  mainf.o:	mainf.c
	cc -g -c mainf.c

  subf.o:		subf.c
	cc -g -c subf.c

  libsubf.so:	subf.o
	ld -o libsubf.so $(FLAG) -lc -lm -G subf.o

  clean:
	rm mainf *.o *.so


$ cat mainf.c
  extern int wrong;
  extern int errno;

  main()
  {
    wrong = 1;
    errno = 1;
    m_subf();
    printf("mmainf() : wrong = %d  &wrong = %p\n", wrong, &wrong);
    printf("mmainf() : errno = %d  &errno = %p\n", errno, &errno);
    l_subf();
    printf("mmainf() : wrong = %d  &wrong = %p\n", wrong, &wrong);
    printf("mmainf() : errno = %d  &errno = %p\n", errno, &errno);
  }

  m_subf()
  {
    printf("m_subf() : wrong = %d  &wrong = %p\n", wrong, &wrong);
    do_it();
  }

  do_it()
  {
    wrong = 2;
    errno = 2;
    printf("m_doit() : wrong = %d  &wrong = %p\n", wrong, &wrong);
    printf("m_doit() : errno = %d  &errno = %p\n", errno, &errno);
  }

$ cat subf.c

  int wrong;
  extern int errno;

  l_subf()
  {
    printf("l_subf() : wrong = %d  &wrong = %p\n", wrong, &wrong);
    do_it();
  }

  do_it()
  {
    wrong = 3;
    errno = 3;
    printf("l_doit() : wrong = %d  &wrong = %p\n", wrong, &wrong);
    printf("l_doit() : errno = %d  &errno = %p\n", errno, &errno);
  }

Set the environment variable LD_LIBRARY_PATH before you start the program
mainf.
$ export LD_LIBRARY_PATH=`pwd`

If the shared library is linked with -Bsymbolic the output of the program
mainf is as follows.
$ mainf
m_subf() : wrong = 1  &wrong = 0x80499d8
m_doit() : wrong = 2  &wrong = 0x80499d8			"wrong" set
to 2 in main source.
m_doit() : errno = 2  &errno = 0x80499d4			"errno" set
to 2 in main source.
mmainf() : wrong = 2  &wrong = 0x80499d8			"wrong" in
main is 2 (ok).
mmainf() : errno = 2  &errno = 0x80499d4			"errno" in
main is 2 (ok).
l_subf() : wrong = 0  &wrong = 0x4001962c			"wrong" in
shared library
l_doit() : wrong = 3  &wrong = 0x4001962c			"wrong" is
set to 3 in library
l_doit() : errno = 3  &errno = 0x80499d4			"errno" is
set to 3 in library.
mmainf() : wrong = 2  &wrong = 0x80499d8			"wrong" in
main source is still 2 (not ok).
mmainf() : errno = 3  &errno = 0x80499d4			"errno" in
main is 3 (ok).

The function main calls l_subf() from the shared library. l_subf() calls
do_it() from the shared library (ok). The variable "wrong" in the shared
library has a different address than the variable "wrong" in the main source
and is therefore a different variable. The function do_it() from the shared
library set "wrong" to 3. But back in the main the value of that "wrong"
variable is still 2. The variable "errno" is both in the main source as in
the shared library the same variable with the same address.

 (If I don't use the option "-Bsymbolic" by creating the shared library the
variable "wrong" in the shared library is the same as in the main source.
  But than the function l_subf() call the function do_it() from the main
source instead of the function do_it() from the shared library and that is
not
  what I need.)

The variable "wrong" is declared as "extern" but a "local" variable "wrong"
is created. Is that correct?
Can I change the sources on such a way that the variable "wrong" in the
shared library is the same as in the main source?

$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs
gcc version 2.96 20000731 (Red Hat Linux 7.1 2.96-85)


Regards,

Hans.



More information about the Gcc-bugs mailing list