LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-16-2006, 09:28 AM   #1
ristiisa
LQ Newbie
 
Registered: Oct 2006
Posts: 8

Rep: Reputation: 0
Static variable sharing in shared libraries


Hello,
I have 2 shared libraries(slave and common) and one binary executable(host). host uses slave and both host and slave use common.
Code:
[host]->[slave]
   \      /
   [common]
In common there is a static variable that can be set/get through commons setCommonValue/getCommonValue functions. I link slave statically with common and host shared with slave and common.
The problem is that when i call a method from slave that calls setCommonValue from common and now i call getCommonValue(in host) the value set in slave is returned.
1) why?
2) how could i link so that this problem does not arise?

The sample output. I expect 1000 and 1000
Code:
$ ./host
1000
Slave acts
500
Code:
$ldd host
        libslave.so => not found
        libcommon.so => not found
        libstdc++.so.5 => /usr/lib/libstdc++.so.5 (0x40027000)
        libc.so.6 => /lib/tls/libc.so.6 (0x400e1000)
        libm.so.6 => /lib/tls/libm.so.6 (0x40216000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x40238000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
Code:
$ldd libslave.so
       libc.so.6 => /lib/tls/libc.so.6 (0x40011000)
       /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x80000000)
Code:
$ nm -g libslave.so | grep ' T '
00000784 T doSlaveStuff
00000830 T _fini
000007ca T getCommonValue
0000062c T _init
000007b0 T setCommonValue
Code:
$ldd libcommon.so
       libc.so.6 => /lib/tls/libc.so.6 (0x40011000)
       /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x80000000)
The code:
make case1 builds my sample.
Code:
//common.h
#ifdef __cplusplus
extern "C" {
#endif

void setCommonValue(int value);
int getCommonValue();

#ifdef __cplusplus
} // extern "C"
#endif
Code:
//common.cpp
#include "common.h"
static int common_value;
void setCommonValue(int value){
        common_value = value;
}

int getCommonValue(){
        return common_value;
}
Code:
//slave.h
#ifdef __cplusplus
extern "C" {
#endif

const char* doSlaveStuff();

#ifdef __cplusplus
} // extern "C"
#endif
Code:
//slave.cpp
#include "slave.h"
#include "common.h"
const char * doSlaveStuff(){
        setCommonValue(500);
    return "Slave acts";
}
Code:
//host.cpp
#include <iostream>
#define SHAREDSLAVE
#include "slave.h"
#include "common.h"
using namespace std;

int main(){
        setCommonValue(1000);
        cout << getCommonValue() << endl;
    cout << doSlaveStuff() << endl;
    cout << getCommonValue() << endl;
    return 0;
}
Code:
#Makefile
all: clean slave slave.so host common

clean:
        rm -f slave.o
        rm -f libslave.a
        rm -f libslave.so
        rm -f libcommon.a
        rm -f libcommon.so
        rm -f host

slave:
        gcc -fPIC -c slave.cpp -o slave.o
        ar -cru libslave.a slave.o

slave.so:
        gcc -shared slave.o -o libslave.so -L. -lcommon

host:
        gcc -u setCommonValue main.cpp -o host -L. -lslave -lcommon -lstdc++

common:
        gcc -fPIC -c common.cpp -o common.o
        ar -cru libcommon.a common.o

common.so:
        gcc -c common.cpp -o common.o
        gcc -shared common.o -o libcommon.so

case1: clean common slave slave.so common.so host
 
Old 10-16-2006, 09:42 AM   #2
xhi
Senior Member
 
Registered: Mar 2005
Location: USA::Pennsylvania
Distribution: Slackware
Posts: 1,065

Rep: Reputation: 45
i dont understand why you are expecting 1000, 1000 when clearly you are setting the value to 1000, and then 500. ??

Code:
const char * doSlaveStuff(){
        setCommonValue(500);
    return "Slave acts";
}
...
int main(){
        setCommonValue(1000);   // <-- you are setting 1000 here
        cout << getCommonValue() << endl;
    cout << doSlaveStuff() << endl;  // <-- you are setting it to 500 here (see above)
    cout << getCommonValue() << endl;
    return 0;
}
or am i missing something?
 
Old 10-16-2006, 09:46 AM   #3
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi -

I think maybe you have the wrong expectations.

A variable is just a variable: it doesn't matter if it's from a shared library (.so), a static library (.a) or a static object (.o) - it's exactly the same in every case.

Here are a couple of links that might explain a bit better:

http://en.wikipedia.org/wiki/Library_(computer_science)
http://www.iecc.com/linker/linker10.html

SUGGESTION:
What's the problem you're really trying to solve? When you said "problem" above, you were actually restating "what" you were doing, not the "why". If we knew the "requirement", the actual goal, then perhaps we could suggest some alternatives for you.

Last edited by paulsm4; 10-16-2006 at 09:49 AM.
 
Old 10-16-2006, 11:44 AM   #4
Tischbein
Member
 
Registered: Oct 2006
Distribution: debian
Posts: 124

Rep: Reputation: 15
Yes, it's the same common variable. Make a "cookie" containing the data specific to each of common's "clients" and get the client to look after it! I mean a struct, of course.

---------
Common:

typedef COMMON_COOKIE {...}

---------
Client such as slave or master:

COMMON_COOKIE my_common;

set_common_value(my_common, 27);

----------
 
Old 10-17-2006, 02:12 AM   #5
ristiisa
LQ Newbie
 
Registered: Oct 2006
Posts: 8

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by xhi
i dont understand why you are expecting 1000, 1000 when clearly you are setting the value to 1000, and then 500. ??

Code:
const char * doSlaveStuff(){
        setCommonValue(500);
    return "Slave acts";
}
...
int main(){
        setCommonValue(1000);   // <-- you are setting 1000 here
        cout << getCommonValue() << endl;
    cout << doSlaveStuff() << endl;  // <-- you are setting it to 500 here (see above)
    cout << getCommonValue() << endl;
    return 0;
}
or am i missing something?
Host uses common as a shared library, but slave uses common in a static library. I thought the memory spaces would not overlap.
 
Old 10-17-2006, 02:18 AM   #6
ristiisa
LQ Newbie
 
Registered: Oct 2006
Posts: 8

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by paulsm4
Hi -

I think maybe you have the wrong expectations.

A variable is just a variable: it doesn't matter if it's from a shared library (.so), a static library (.a) or a static object (.o) - it's exactly the same in every case.

Here are a couple of links that might explain a bit better:

...

SUGGESTION:
What's the problem you're really trying to solve? When you said "problem" above, you were actually restating "what" you were doing, not the "why". If we knew the "requirement", the actual goal, then perhaps we could suggest some alternatives for you.
Well the problem is how to use common so that the variable would stay unchanged in host if slave changes it and vice versa? Consider the common to be a third-party library that both host and slave would like to use simultaneously.
 
Old 10-17-2006, 02:21 AM   #7
ristiisa
LQ Newbie
 
Registered: Oct 2006
Posts: 8

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by Tischbein
Yes, it's the same common variable. Make a "cookie" containing the data specific to each of common's "clients" and get the client to look after it! I mean a struct, of course.

---------
Common:

typedef COMMON_COOKIE {...}

---------
Client such as slave or master:

COMMON_COOKIE my_common;

set_common_value(my_common, 27);

----------
In this case changing the common is not an option. But good suggestion.
 
Old 10-17-2006, 03:58 AM   #8
ristiisa
LQ Newbie
 
Registered: Oct 2006
Posts: 8

Original Poster
Rep: Reputation: 0
I read about -Bsymbolic option in gcc, it seemed thats what i need, but no effect whatsoever. any ideas?
 
Old 10-17-2006, 05:32 AM   #9
ristiisa
LQ Newbie
 
Registered: Oct 2006
Posts: 8

Original Poster
Rep: Reputation: 0
In this case are there duplicate symbols? One get/setCommonValue in common and one in slave(when linked staticly with common).

I did a experiment:
Code:
#include "common.h"
static int common_value1;
static int common_value2;
void setCommonValue(int value){
        #ifdef USEVAL1
        common_value1 = value;
        #else
        common_value2 = value;
        #endif
}

int getCommonValue(){
        #ifdef USEVAL1
        return common_value1;
        #else
        return common_value2;
        #endif
}
I compiled common with -DUSEVAL1 and then compiled slave and linked them. Then i compiled common winthout USEVAL1 into shared library. But no success...
 
Old 10-19-2006, 05:13 AM   #10
ristiisa
LQ Newbie
 
Registered: Oct 2006
Posts: 8

Original Poster
Rep: Reputation: 0
Well i have solved the problem by implementing a version script. So...
Code:
$ cat slave.v
{ global: doSlaveStuff; local: * ; };
And i compiled the project with...
Code:
gcc -Wall -fPIC -c common.cpp -o common.o
ar -cru libcommon.a common.o
gcc -Wall -fPIC -c slave.cpp -o slave.o
gcc -Wall -shared -Wl,--version-script=slave.v slave.o -o libslave.so -L. -lcommon
gcc -Wall -shared common.o -o libcommon.so
gcc -Wall main.cpp -o host -L. -lslave -lcommon -lstdc++
Finally...
Code:
$ ./host
1000
Slave acts
1000
I thank everybody for their help.
Cheers!
 
Old 10-19-2006, 07:47 AM   #11
xhi
Senior Member
 
Registered: Mar 2005
Location: USA::Pennsylvania
Distribution: Slackware
Posts: 1,065

Rep: Reputation: 45
interesting... what is the version script doing?
 
Old 10-19-2006, 10:43 AM   #12
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
ristiisa -

I strongly suspect that whatever you *think* you got working is probably more by coincidence than by design. I still think you've got some fundamental misconceptions about how processes can access and share global data with each other, and about what shared libraries can (or cannot!) do for you.

Please do glance at these links (if you haven't already):

http://en.wikipedia.org/wiki/Shared_libraries
http://www.iecc.com/linker/linker10.html
http://people.redhat.com/drepper/dsohowto.pdf

IMHO .. PSM

Last edited by paulsm4; 10-19-2006 at 10:46 AM.
 
Old 10-19-2006, 01:32 PM   #13
exvor
Senior Member
 
Registered: Jul 2004
Location: Phoenix, Arizona
Distribution: Gentoo, LFS, Debian,Ubuntu
Posts: 1,537

Rep: Reputation: 87
I was gonna say make them static or just pass the value to the functions and not use a golbal variable. Then again this is C++ witch I stay away from
 
Old 10-20-2006, 09:08 AM   #14
ristiisa
LQ Newbie
 
Registered: Oct 2006
Posts: 8

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by paulsm4
ristiisa -

I strongly suspect that whatever you *think* you got working is probably more by coincidence than by design. I still think you've got some fundamental misconceptions about how processes can access and share global data with each other, and about what shared libraries can (or cannot!) do for you.

Please do glance at these links (if you haven't already):

http://en.wikipedia.org/wiki/Shared_libraries
http://www.iecc.com/linker/linker10.html
http://people.redhat.com/drepper/dsohowto.pdf

IMHO .. PSM
The real life problem was that i had a application using Qt and a shared library using Qt. Both designed so that using them together resulted conflict in sharing Qt's global variables(like db connections and text codecs). The reason was in the design of that shared library, designed to be cross platform but forgot to take notice about shared library behavior under linux. Perhaps the solution i found was a mere coincidence or a loophole but on windows dll's act like that in the first place. You have to go extra trouble for wanting to export your symbols and to import foreign exported symbols. If i compile the same project under windows with gcc and with ms compiler then gcc exports everything and cl exports nothing.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Linking static and shared libraries in the KDevelop Environment tristanm Programming 15 11-27-2006 09:59 PM
shared libraries, dlopen and static member variables? (C/C++) Thinking Programming 2 12-19-2005 12:55 AM
Making static symbols private/local in shared libraries skoona Programming 1 02-18-2005 03:14 PM
compiling with shared and static libraries jinksys Programming 1 11-22-2003 04:54 AM
gaim trying to link static and shared libraries rose_bud4201 Linux - Software 0 09-28-2003 12:27 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:25 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration