2012-12-31 4 views
7

編集:インクルードガードについて知っていますが、インクルードファイルはではなく、の問題です。私は、実際にコンパイルされ、すでにリンクされているコードについて、スタティックライブラリに焼き付けられていることについて話しています。C++ライブラリを使用するときに同じコードを含むことを避けるにはどうすればよいですか?

私は自分用の汎用ユーティリティライブラリをC++で作成しています。

私が作成している機能の1つであるprintFileは、stringcoutなどの標準ライブラリのメンバーが必要です。

私はライブラリがコンパイルされ、その後もstringcoutを使用して、別のプロジェクトにリンクされている場合、stringcoutのコードが複製されることを心配している:それは、両方のプログラムがあるライブラリのバイナリにプレリンクされますリンクされており、それ自体を使用するプロジェクトと再びリンクされます。

ライブラリは次のように構成されています

  1. 1つのlibname.hppファイル彼のプロジェクトで#includeになっているライブラリを使用して、プログラマがあります。
  2. libname.hppで宣言されたすべての関数fnameには、ファイルfname.cppが実装されています。
  3. すべてfname.cppファイル#include "libname.hpp"もあります。
  4. ライブラリ自体はlibname.aにコンパイルされ、/usr/lib/にコピーされます。

これは起こりますか?
はいの場合は、まったく問題ですか?
はいの場合、どうすればこの問題を回避できますか?

答えて

3

私はライブラリがコンパイルされ、その後も文字列とCOUTを使用して、別のプロジェクトにリンクされている場合、文字列とCOUTのコードが

を複製されることを心配しては心配しないでください。現代のコンパイルシステムはそれをしません。テンプレート関数のコードはオブジェクトファイルに出力されますが、リンカは重複するエントリを破棄します。

0

はい、標準ライブラリのもののコードは複製されます。たとえば、std :: stringを返す場合や、メソッドのいずれかでパラメータとして取得する場合に問題になる可能性があります。標準のライブラリ実装では、ユーザのレイアウトとは異なるレイアウトを持つことがあります。

+1

OK、わかりました。しかし、 "これを避ける方法"は私の質問の大きな部分です。 – corazza

+0

私は、コードの複製と標準ライブラリクラスのレイアウトという2つの異なる問題を混在させていたことに気付きました。ライブラリをコンパイルするのに使ったのと同じコンパイラでプログラムをコンパイルしているのであれば、2番目の問題は問題にはなりません。最初のコードでは、コードが大きくなる可能性がありますが、そうでなければ実際には問題にはなりません。 – user1610015

3

標準C++ライブラリのライブラリ定義は、そこに明示的に含めない限り(つまり、標準C++ライブラリからオブジェクトファイルを抽出してライブラリに組み込む場合を除いて)独自の静的ライブラリには表示されません。静的ライブラリはまったくリンクされておらず、他のライブラリへの未定義の参照を持つだけです。静的ライブラリは、ライブラリによって提供されるシンボルを定義するオブジェクトファイルの集合です。インライン関数やテンプレートのインスタンス化などのヘッダーからの定義は、複数の翻訳単位の複数の定義が矛盾しないように定義されます。コードが実際にインライン化されていない場合、リンク時に重複が無視または削除される「弱い」記号が定義されます。

実行可能ファイルにリンクされたライブラリは、互換性のあるライブラリ定義を使用する必要があります。相当量のコードがヘッダーファイルに存在するため、C++ヘッダーファイルには比較的頻繁な変更が行われます(標準的なC++ライブラリヘッダー(コードが大幅に少なくなっているCライブラリーヘッダーを基準にしています)。

0

これはほとんど問題ではありません。

ヘッダファイルに定義されている関数とインラインテンプレート関数の場合、すべてのコンパイル単位に独自のコピーがあります(例えば、.aライブラリ内には匿名コピーが多数ある可能性があります)。これらの定義はエクスポートされないので、リンカはそれらについて心配する必要はないので、これは問題ありません。

非静的リンケージで宣言されている関数の場合、問題があるかどうかは、.aライブラリのリンク方法によって異なります。

ライブラリをビルドするときは、通常、標準のC++ライブラリででなく、のリンクになります。作成されたライブラリには、標準C++ライブラリへの未定義の参照が含まれます。これらは、最終実行可能バイナリを構築する前に解決されなければなりません。これは通常、最終バイナリをデフォルトの方法で(コンパイラによって)リンクするときに自動的に行われます。

人々が標準C++ライブラリで静的ライブラリにリンクしていることがあります。別のライブラリ(標準のC++ライブラリのような)を埋め込んでいる複数の静的ライブラリとリンクしている場合は、それらの埋め込みライブラリに違いがある場合には、問題が生じることを期待してください。幸いにも、これは少なくともgccツールチェーンではまれな問題です。 Microsoftのツールではmore frequent problemです。

場合によっては、1つまたは複数の競合する静的ライブラリを動的ライブラリにすることを回避することができます。このようにして、これらの各動的ライブラリは、問題のあるライブラリの独自のコピーを静的にリンクできます。ダイナミックライブラリが問題のライブラリからシンボルをエクスポートせず、メモリレイアウトの非互換性がない限り、一般的に問題はありません。