動的ライブラリ中のグローバル変数

このQ&Aのポイント
  • 動的ライブラリ中のグローバル変数について調べました。
  • mainと動的ライブラリsub1.soとsub2.soの間での変数の共有について問題があります。
  • sub2.soのTEST変数がundefined symbolとなる現象が発生しています。
回答を見る
  • ベストアンサー

動的ライブラリ中のグローバル変数

以下の3行を前提条件とします。 メインのプログラムmainと動的ライブラリsub1.soとsub2.soがあります。 sub1.cとsub2.cにはsub.hというヘッダをインクルードしています。 mainはsub1.soおよびsub2.soを実行時に動的にリンクします。 ここでsub1.c中で int TEST=10;と変数を定義しました。 さらにsub.h中にextern int TEST;と変数を宣言しました。 そしてsub2.h中で if(TEST){…}と記述しました。 この状態でコンパイルを実行しました。 ここでmainを実行すると動きません。 調べてみるとsub2.soがTESTがundefined symbolとなっていました。 動的ライブラリ間での変数の共有の仕方は上の書き方では不正確なのでしょうか?

noname#182748
noname#182748

質問者が選んだベストアンサー

  • ベストアンサー
  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.1

コード自体はそれでいいはずですが、sub2.soを作る際にsub1.soへの依存(動的リンク)があることを指示してないんでは?

noname#182748
質問者

お礼

回答ありがとうございます。試してみます。 返信がおくれてもうしわけありませんでした。

関連するQ&A

  • 共有ライブラリ作成時の -L

    sub1.c sub2.cからlibsub1.so libsub2.soを作成し、main.cをコンパイルします。 いずれのファイルも/rootにあります。 ここで gcc -c sub1.c gcc -shared -o libsub1.so sub1.o gcc -c sub2.c gcc -shared -o libsub2.so sub2.o gcc -o main main.c libsub1.so  libsub2.so だけでは [root@localhost ~]# ldd main linux-gate.so.1 => (0x0020d000) libsub1.so.1 => not found libsub2.so.1 => not found libc.so.6 => /lib/libc.so.6 (0x003e3000) /lib/ld-linux.so.2 (0x003c4000) でロードされていないので ln -s /root/libsub1.so /usr/lib/libsub1.so ln -s /root/libsub2.so /usr/lib/libsub2.so で/usr/libにシンボリックリンクを張る必要があります。 このリンクをはる作業をなんとかしてコンパイラのオプションを用いて省略したいとおもっています。 そこで gcc -o main main.c -L/root/libsub1.so -L/root/libsub2.so としたのですが /tmp/cc4Ccfom.o: In function `main': main.c:(.text+0x12): undefined reference to `print' collect2: ld はステータス 1 で終了しました make: *** [main] エラー 1 になってしまいました。 上の状況で質問は2つあります。 (1)gccのオプションを用いてシンボリックリンクを張る作業を省略するにはどうすればいいでしょうか?(私はーLの使い方を見よう見まねで用いたのですがまずかったようでエラーがでました。) (2)上のエラーは何が原因だったのでしょうか? ソースは //sub1.c #include "sub.h" int TEST=10; //sub2.c #include "sub.h" #include <stdio.h> void print(void) { if(TEST) printf("TEST is HOGE!\n"); } //main.c #include "sub.h" #include <stdio.h> int main(void) { print(); return 0; } //sub.h extern int TEST; です。 どちらかでも回答できるかたがいらっしゃれば、お願いします。

  • グローバル変数

    分割コンパイルで、持ちいる変数をヘッダーファイルに宣言しました。 ヘッダーファイル内で次のように宣言し、メインの関数でない場合にはexternになるようにしました。 メインなら FILEは1 それ以外なら0 #if FILE   unsinged int inputNo; #else  extern unsigned int inputNo; #endif しかし、リンクをさせると error LNK2001: 外部シンボル "_inputNo" は未解決です と出てしまいます。解決策はあるでしょうか? プロジェクトの設定の関係でしょうか?よろしくお願い致します。

  • SolarisとLinuxのグローバル変数の扱いについて

    Solaris用のソースをLinuxで使えるように変更したいのですが、 グローバル変数について以下のようなことが発生していて困っています。 なにか、コンパイルオプションなどで対応はできないものでしょうか? Solaris (CC)では 特にextern宣言しなくても同じシンボルの外部変数はコモンセグメントに1つだけ作成しコンパイル自体は正常である。 しかし、Linux (g++)では externを宣言しないと同じシンボルを再定義したことになりエラーとなる。 これにより、グローバル変数を多用しているプログラムはLinuxでうまくコンパイルができない。 しかし、単純にextern宣言での対応は難しい。 extern宣言は外部で定義してあるグローバル変数を参照する というものだがLinux では 1つの定義を意外は全てexternしなければ、2重定義エラーになってしまう。 つまり、実体が1つであとはそれを参照しているという形でなければいけない。 ところが、その実体をどこにするか特定することができない。 例えば、gというグローバル変数を仮定する。 A.c,B.c,C.cはその3つのソースよりAA.aという静的ライブラリを構成する。 gはA.cで定義してありB.c,C.cはそれを参照する。 ところが C.cは個別にC.oというオブジェクトで他からの呼び出しがあり 別LMにリンクされる。 その時C.c内のgは実体を失うことになり未定義となる。 つまり、どれが実体になるかは何にリンクするかで決まるため 実態を特定できない。 また、共通のヘッダにグローバル変数が定義されている場合も、重複するというエラーを起こすため、 共通ヘッダからグローバル変数を分離し、何れかのソースにグローバル変数の実態を定義させる必要がある。 共通ヘッダを使っている他のソースはそのグローバル変数の実態を参照するようにexternの宣言をする。

  • 分割コンパイルでのファイル利用について

    分割コンパイルする際、例えばsub.cで fpi=fopen(argv[1], "rb") のようにファイルを開き、それを別のmain.cで 引き続き利用したい場合、どのようにして引き渡せば良いでしょうか? ヘッダファイルを利用してみたのですが、なぜか実行すると 「外部シンボル'_fpi'が未解決」などとエラーが出てしまいます。 ヘッダファイルについては、head.hに extern FILE *fpi,*fpo; と 入れておいて、main.cとsub.cに #include "head.h" を入力してある状態です。 使っているのは Microsoft Visual C++ Express Editionです。 よろしくお願いします。

  • C言語 extern について

    どうもこんにちは C言語でプログラムを作っています。 複数のファイルから1つのプログラムを作っていますが、あるファイルで実装した関数を別のファイルから使用する際、単にプロトタイプ宣言を行うだけでなく、extern が必要なのでしょうか? 今までは extern を使用せず、以下のように書いてました。 // main.c ファイル int func_sub(); int func_main() { return func_sub() * 2; } // sub.c ファイル int func_sub() { return 10; } これは extern を使用して、このように書かないとだめなのでしょうか? // main.c ファイル extern int func_sub(); // このexternは必要? int func_main() { return func_sub() * 2; } // sub.c ファイル int func_sub() { return 10; } 大域変数を他のファイルでも使用する場合はexternが必要ですが、関数に関してもexternを使用しなければならないのでしょうか?

  • javaのローカル変数について

    基本的なことの質問ですがよろしくお願いいたします。 下記の様なソースコードでint y ;はローカル変数にあたると思いますが 確かローカル変数は初期化されないとコンパイルエラーになるはずなのですが どうもコンパイルも実行もできます。 どうしてでしょうか? よろしくお願いいたします。 class Test1{ static int x = 0; } public class Test extends Test1{ public static void main(String args[]){ Test i = new Test(); int y ; y = ++x; System.out.println( y ) ; } }

    • ベストアンサー
    • Java
  • C言語でヘッダファイルにグローバル変数を宣言する

    main.hに static int a; と記述し、main.cで #include "main.h" [省略] a=10; のように使用して、-Wallをつけてコンパイルすると、main.cで使用しているにも関わらず、 'a' defined but not used という警告が表示されます。 同様に、関数においても、ヘッダファイルでstaticをつけると ‘~’ declared ‘static’ but never defined と警告されます。 静的グローバル変数などは、ソースファイル内で宣言しなければいけないのでしょうか?ヘッダファイル内で宣言しても警告が出ないような方法はありますか?

  • linuxにおけるCの自作ヘッダファイル

    現在C言語のしっかりと学ばなかった部分を学習したいと思い、自作ヘッダファイルの作成を勉強しています。 そこで、書籍のその章を一通り読んだあと、自分で簡単なものを作成してみましたが、エラーが出てうまくいきません。 どうしてかわかる方いたら教えてください。 コード *****main.c***** #include "print.h" int main(void) { print(); return 0; } *****print.c***** #include <stdio.h> void print(void) { printf("test\n"); } *****print.h***** extern void print(void); エラー /tmp/ccH551c1.o: In function `main': /home/ユーザ名/Documents/StudyC/main.c:5: undefined reference to `print' collect2: ld returned 1 exit status CentOS6.6にて端末上での実行です。 自分の解釈では、""でincludeすることでカレントディレクトリから目的のヘッダファイルを見つけ出してインクルードする、また、ヘッダファイル内でexternすることによってprint.cから目的の関数を定義しているので、main.cでは問題なく使えると思っています。 しかし、エラーではprint()が定義されていないと出るのでまったくわかりません・・・。

  • 大域変数について

    配列の大域変数externの使いかたがよくわかりません。 BCC Developerを用いて分割コンパイルをしています。 headerファイルにて配列 int map[10][10]; と定義してその配列を他のファイルで使いたい場合は extern int map; ではいけないのでしょうか? あと、headerにて static int * map[10][10] と記述して他のファイルにて extern int *map という記述の仕方は可能なのでしょうか? 大域変数なのにstaticを用いるのはおかしいかとおもいますが… ご教授よろしくお願いします。

  • Makefileと共有ライブラリ

    main.c sub1.c sub2.cに対して 共有ライブラリlibsub1.soとlibsub2.soを生成して それをもちいてmainをコンパイルするMakefileを以下のように記述しました。 CC=gcc LIB= CFLAGS=-Wall TARGET = main SHAD = -shared .SUFFIXES:.so .o SRCS = main.c libsub1.so libsub2.so $(TARGET):$(SRCS) $(CC) -o $@ $(SRCS) @echo "make finished!!" #.o.so: # $(CC) $(SHAD) -o $@ $< libsub1.so:sub1.o gcc -shared -o libsub1.so sub1.o libsub2.so:sub2.o gcc -shared -o libsub2.so sub2.o .c.o: $(CC) -c $< #sub1.o:sub1.c # gcc -c -fPIC sub1.c #sub2.o:sub2.c # gcc -c -fPIC sub2.c clean: @rm -f libsub?.so sub?.o ここで.oから.cを生成するのはサフィックスでできたのですが、同じように.oから.soを生成するのは できませんでした。 #.o.so: # $(CC) $(SHAD) -o $@ $< ここはどのように記述したらいいのでしょうか? 回答お願いします。

専門家に質問してみよう