• ベストアンサー

共有ライブラリの作成について

呼び出した関数名の名前を表示させる、 テスト用共有ライブラリ「testLib.so」を作成しようと思っています。 そしてそのライブラリを他のプログラムから呼び出すというものです。 以下、内容。 int test1(void){ printf("test1 program."); } int test2(void){ printf("test2 program."); } int test3(void){ printf("test3 program."); } 【パターン1】 上記関数毎でファイル分けし、 test1.c、test2.c、test3.c と言うファイルを作成。 これらの各オブジェクトを取り込んで共有ライブラリを作成するパターン。 【パターン2】 全ての関数を「testDisp.c」と言うファイルに記述し、 このオブジェクトファイルで共有ライブラリを作成するパターン。 上記パターン1と2では用途によって使い分け方法があると言う話を先日聞いたのですが、どの様な場合に1、どの様な場合に2のパターンを使用するのでしょうか。 宜しくお願い致します。

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

  • ベストアンサー
  • trapezium
  • ベストアンサー率62% (276/442)
回答No.1

dynamic linkではそれほど違いはないと思いますが、むしろstatic libraryだと細かく分けておいた方が最終的に実行ファイルのサイズを小さく出来ます。厳密にはシンボル解決のオーバーヘッドが多少増えたり、コンパイラの最適化などにも影響するかもしれません。

megumi1122
質問者

お礼

質問を締め切らせて頂きます。 お二方のご意見、大変参考になりました。 回答して頂きありがとうございます。 甲乙つけ難く、 一番初めに回答下さった方を良回答とさせて頂きました。

megumi1122
質問者

補足

と言う事は【パターン1】の場合、実行ファイルのサイズは小さくなりますが、シンボル解決のオーバーヘッドの増加やコンパイラの最適化に影響すると言う事により、 結果として処理時間、メモリ使用量、消費電力の増加に繋がる可能性があるという解釈で宜しいでしょうか。 再度見て頂けましたら、お手数ですが回答の程宜しくお願い致します。

その他の回答 (1)

  • chie65535
  • ベストアンサー率43% (8524/19375)
回答No.2

静的ライブラリの場合、関数は「1ソース単位」で実行ファイルに取り込まれます。(正確には「1オブジェクト単位」) パターン1の場合、test1を呼び出すと、実行ファイルにはtest1だけが取り込まれ、test2、test3は取り込まれません。 パターン2の場合、test1を呼び出すと、実行ファイルにはtest1、test2、test3のすべてが取り込まれます。呼びもしていない無用なtest2、test3が実行ファイルに存在する事になります。 もし、test2、test3が「巨大な関数」であれば、実行するたびに「無用な関数の為に、不必要なロードが行われ、余計なメモリを食う」と言う事になります。 パターン1は「それぞれが独立した関数になっている場合」の作り方です。 パターン2は「各関数に関連性があり、どれか1つを使う場合は、他の関数も必ず使う場合」の作り方です。 例えば、fopenとfcloseは必ずセットで使うので、同一のソース(オブジェクト)になっているのが普通です。fopenしておきながらfcloseしない、なんて書き方は普通はしませんし、fopenしてない物はfcloseできませんから。

megumi1122
質問者

お礼

質問を締め切らせて頂きます。 お二方のご意見、大変参考になりました。 回答して頂きありがとうございます。 甲乙つけ難く、 一番初めに回答下さった方を良回答とさせて頂きました。

megumi1122
質問者

補足

パターン1、パターン2、それぞれに対し、大変わかり易い回答大変ありがとうございました。 更に自分でも色々調べてみようと思っております。 勉強になりました。

関連するQ&A

  • 静的ライブラリについて教えて下さい

    静的ライブラリについて教えて下さい。作成方法は大体わかったのですが、使い方と利用シーンがわかりません。例えば、 -main.c- #include <stdio.h> #include "abc.h" int main(){ a(); b(); c(); } -a.c- #include <stdio.h> void a(void){ printf("a\n"); } -b.c- #include <stdio.h> void b(void){ printf("b\n"); } -c.c- #include <stdio.h> void c(void){ printf("c\n"); } -abc.h- void a(void); void b(void); void c(void); というファイルを作成した上で以下のようにコンパイルしました。 gcc -c a.c gcc -c b.c gcc -c c.c これで、a.o, b.o, c.oというオブジェクトファイルが出来ました。 次にar rcs static a.o b.o c.oとコマンドを打ったところ、問題なくstaticという静的ライブラリと思われるファイルが出来ました。で、そもそもですがこの使い方がわかりません。main.cをコンパイルする際に使うのでしょうか?そもそも上で作成した静的ライブラリにはmain.oも含めるべきものでしょうか?初歩的な質問ですみません。宜しくお願いします。

  • Linux C言語共有ライブラリを作成するときの

    RedHatLinux7.3(2.96-110)、gcc(2.96 20000731)です。 C言語で共有ライブラリを作成しています。このライブラリは呼び出し側のプログラム起動時にロードされるものなのですが、以下の2つの手順で生成されたライブラリは、どのような違いがあるのでしょうか? どちらも呼び出し側からは関数コールで実行できるのですが、どちらが正しいのでしょうか? 【その1】 1) gcc -shared -o libxxx.so xxx.c (ライブラリ生成) 2) gcc ./libxxx.so -o testcall testcall.c (呼び出し側とライブラリをリンクして実行ファイル生成) 【その2】 1) gcc -fPIC -c libxxx.c(ライブラリのオブジェクト生成) 2) gcc -fPIC -c -shared -Wl,-soname,libxxx.so.0 -o libxxx.so.0.0 xxx.o(共有ライブラリ生成) 3) soname設定 4) linkername設定 5) gcc -c -o testcall.o testcall.c(呼び出し側オブジェクト生成) 6) gcc -o testcall testcall.o -lxxx 7) LD_LIBRARY_PATH設定、exportする 以上、ご存知のかた、どうぞよろしくお願いします。

  • コンパイラ、その周辺の質問

    C言語を勉強していて、いまいちわからなかったことを、ないがしろにしていたのでここで質問させてください。 ・あるプログラムをコンパイルするとまず機械語に翻訳されオブジェクトファイルができ、リンクすることでライブラリに登録されている関数のオブジェクトファイルと結合させ1つの実行ファイルを作るのですよね?(ここまでまちがいない?)  例えばprintf()を使ったときコンパイラはどのようにしてそのprintf()のオブジェクトファイルを探しているのかよくわかりません。ライブラリ(.lib)の働きも良くわかっていません。 VC++を使っておりますが、自作の関数をライブラリに登録する方法もできれば教えていただきたいです。 よろしくお願いします。

  • ライブラリのリンクについて。

    ふと、疑問に思ったので質問させてもらいます。 C言語などでプログラムを作る時、ライブラリをリンクさせて使うと思いますが、その場合プログラムを実行させた場合メモリー上ではどうなるのか教えた貰いたいです。 例えばprintf関数を使う場合その命令そのものがプログラムに組み込まれてメモリーに読み込まれているのかということです。 前にどこかで読んだ記憶があるのですが、いろいろなところから呼び出される標準的なものはシステムで一箇所にありそれを使うなどということがあったような無かったような記憶があやふやですが見た覚えがあるので気になってしまいました。 あとライブラリなどから一つだけ関数を使う場合、使わない他の関数などもメモリーに読み込まれていたりするのでしょうか? よく使う自分で作った関数を一つのファイルにまとめ、それを定義したヘッダーファイルをincludeした場合も同様で使わないほかの関数はどうなるのでしょうか?

  • ライブラリ関数について教えてください

    C言語を独学で勉強しています。 ファイルの中のデータと配列データが一致するかを調べるプログラムを作ろうとしています。 しかし、私が作っているプログラムでは表示結果が正しくありません。 char型では==を使って一致かどうかを調べることが出来ないので、ライブラリ関数を使う必要があることを知ったのですが、調べてもよくわかりませんでした・・・ どのように作ればいいのか詳しく教えていただけないでしょうか。 よろしくお願いします。 #include<stdio.h> struct test { char no[5]; char name[10]; char english[5]; char math[5]; }; int main(void){ FILE *fp; int i; char f_no[5], f_name[5]; struct test data[5] = { {"001","akemi","100","40"}, {"002","tadao","59","76"}, {"003","mika","94","69"}, {"004","hiroshi","54","98"}, {"005","kazu","39","57"} }; struct test *test_p; test_p = data; if ((fp = fopen("test.txt", "r")) == NULL) { printf("NOT OPEN FILE\n"); } else { while (fscanf(fp, "%s%s", f_no, f_name) == 2) { for(i = 0; i<=5; i++) { if((test_p->no == f_no) && (test_p->name == f_name)) { printf("%s %s 英語%s 数学%sです。\n", f_no, f_name, test_p->english, test_p->math); } else { printf("%s %s 一致しません\n", f_no, f_name); break; } ++test_p; } } } fclose(fp); }

  • 既に定義されている関数のプロトタイプがない警告

    現在、Cで作られたプログラムの単体テストをしています。 これを、以下のように、 ・testBase.h → テストのための表示とかを作成するためのもの ・progForCheck.c → これがチェックすべきもので、この中の関数をそれぞれチェック ・add.c など → main() を含んだ、チェックを実行するためのファイル として、以下のような感じで関数分のテストプログラムを作成してテストしようとしています。 テスト自体は問題ないのですが、この構成でコンパイルをすると、 警告 W8065 test.c 13: プロトタイプ宣言のない関数 'writeFotter' の呼び出し(関数 main ) 警告 W8057 test.c 15: パラメータ 'argc' は一度も使用されない(関数 main ) という警告が出ます。後者はその通りで問題ないのですが、前者の警告は、よくわかりません。 実体は3つのファイルですが、コンパイル時にはひとつのファイルになって、既に定義されている writeFotter() を呼んでいるだけなのに、「プロトタイプがない」という警告が出るのは、なぜなのでしょう。 それに、writeHeader() や、doCheck() は警告も無しです。 とりあえず、リンクも正常でちゃんと動作しているようなのですが、ちょっと気持ち悪いので質問しました。 // --------------- testBase.h ---------- #include <stdio.h> int OK = 0; int NG = 0; void doCheck(int isOK) { if (isOK) OK++; else NG++; } void writeHeader(char *title) { printf(" ------------ %s ------------\n", title); } void writeFotter() { printf(" OK = %d, NG = %d", OK, NG); if (NG == 0) printf(" ○○○○○○○○○○○○○○○○○○○\n"); else printf(" ×××××××××××××××××××\n"); } // ------------ progForCheck.c int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } // ------------ test_add.c #include "testBase.h" #include "progForCheck.c" int main(int argc, char *argv[]) { writeHeader(argv[0]); doCheck(add(1, 2) == 3); doCheck(add(2, 4) == 6); doCheck(add(8, 1) == 9); writeFotter(); return 0; }

  • 共有ライブラリの関数はヘッダファイル不要?

    http://www.ncad.co.jp/~komata/c-kouza26.htm ↑のページのコードを自分で書いてみましたが、 確かに概ね書いてる通りに動きました。 共有ライブラリの関数を使用するのに、 ヘッダファイルや関数プロトタイプは不要なのですか? (動的)リンクの際に、mainより先に 共有ライブラリの関数が先に読み込まれているということですか? http://d.hatena.ne.jp/sleepy_yoshi/20090510/p1

  • 関数の引数表記なしについて

    はじめまして。C言語初心者です。 質問させてください。 関数を宣言して引数を表記しないで使用することは可能なのでしょうか? またどのような場合に使用するのでしょうか? 例として以下コードになります。 ----------------------- #include<stdio.h> int test1(int a); void test2(int b); void main(){ int i = 0; int j = 0;       //この部分 i = test1; printf("%d\n", i);        //この部分 j = test2; printf("%p\n", j); } int test1(int a){ return a + 1; } void test2(int b){ printf("test"); } --------------------------- 出力結果を見ると関数のアドレスが帰ってくるように思われますが、詳細が分かりません。 詳しい方がいらしましたら教えてください。 宜しくお願いいたします。

  • 共有ライブラリ作成時の -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; です。 どちらかでも回答できるかたがいらっしゃれば、お願いします。

  • 関数とポインタについて

    #include <stdio.h> void test(int *p); int main() { int i; test(&i); printf("%d",i); return 0; } void test( int *p) { static int k; k = 10; p = &k; } このようなプログラムを作って、void test()のkの値をmain関数で受け取りたいのですが、どのようにすればよいのかわかりません。 どなたか教えていただけませんか?

専門家に質問してみよう