Section:1 2 3 4 5 6 7 8 9 10 11 12 13 14 A B C D E

14 Libraries and Header File Inclusion(ライブラリとヘッダファイルのインクルード)

ライブラリはインタフェースの情報を記録するために使用されます。 標準C言語ライブラリについての情報を含むライブラリは ライブラリの呼び出しのチェックを有効にするために使用されます。 プログラムライブラリは大規模なプログラムの中で単一のモジュール の高速チェックを有効にするために作成されます。

14.1 Standard Libraries(標準ライブラリ)

ライブラリの関数の呼び出しをチェックするために、 Splintはアノテーションが付けられた標準ライブラリを使用します。 これは、関数のインタフェースについてのより詳細な情報を含み、それから、 アノテーションを使用するため、 システムのヘッダファイルで提供されています。 さらに、それは、ISO C99標準でドキュメント化されている関数のみを 含んでいます。 多くのシステムではそれらのシステムライブラリ内に追加関数を含みます; これらの関数を使用するプログラムは、それらを提供していない他のシステム上では コンパイルすることは出来ません。 ライブラリで定義されている特定の型は抽象型として扱われています (例えば、プログラムはFILE型がどのように 実装されているかに依存してはなりません)。 ソースコードをチェックする際、Splintはライブラリ内のファイルに対応した システムヘッダを含んでいますが、しかし、代わりに、 標準ライブラリのライブラリ説明を使用します。

Splintの配布物にはいくつかの異なる標準ライブラリが 含まれています: ANSI標準ライブラリ、POSIX標準ライブラリ *19、そして、Open GroupのSingle Unix Specification(唯一のUNIX仕様)に基づく、 UNIXライブラリです。 それぞれのライブラリには2つのバージョンがあります: 標準バージョンと厳格バージョンです。

14.1.1 ISO Standard Library(ISO標準ライブラリ)

Splintの規定の動作はISO標準ライブラリ(standard.lcdからロードされる) を使用することです。 このライブラリはISO C99標準に記述されている標準ライブラリに基づいています。

14.1.2 POSIX Library(POSIXライブラリ)

POSIXライブラリは+posixlibフラグにより選択されます。 POSIXライブラリはIEEE Std 1003.1-1990に基づいています。

14.1.3 UNIX Library(UNIXライブラリ)

UNIXライブラリは+unixlibフラグにより選択されます。 このライブラリはOpen GroupのSingle Unix Specificationのバージョン2に基づいています。 free関数は nullではない引数で宣言されています。 ISOはfree関数が引数にNULLを扱えると明記していますが、 しかし、いくつかのUNIXプラットフォームでは NULLfree関数に渡されるとクラッシュします。

14.1.4 Strict Libraries(厳密なライブラリ)

ライブラリのより厳格なバージョンが使用されるのは、 -ansi-strictposix-strict-libあるいは unix-strict-libフラグが使用された場合です。 これらのライブラリはライブラリのより厳格な解釈を使用します。 それらはいくつかのプログラムではより多くのエラーを検出しますが、 典型的なコードに対してより多くの偽のエラーを生成する可能性があります。

標準のライブラリと厳格なライブラリの違いは以下の通りです。

  • 標準のライブラリではエラーコードを返す可能性のある出力関数(fprintfprintfsprintf)がintではなくvoidを戻すように宣言しています。これは、典型的なプログラムに対して、戻り値の無視のエラーが圧倒的な量にならないようにしますが、いくつかの適切なエラーが検知されないことを意味するかもしれません。厳格なライブラリではintを戻すように宣言されています。そのため、戻り値の無視のエラーが(他のフラグの設定に応じて)報告されるでしょう。プログラムはこの戻り値が負の値ではないことを確認する必要があります。
  • 標準のライブラリはいくつかの引数と戻り値を代替型(int あるいは boolint あるいは char)としています。ISO C99標準では古いバージョンのライブラリとの互換性のため、intとしてこれらの型を指定していますが、論理的にはbool あるいはcharの方が理にかなっています。厳密なライブラリでは、より強い型が使用されます。assertへの引数は、標準的なライブラリではintあるいはboolであり、厳密なライブラリではboolです。文字関数、isalnumisalphaiscntrlisdigitisgraphislowerisprintispunctisspaceisupperisxdigittolower、と、toupperへの引数は、標準のライブラリではcharあるいは unsigned char あるいはintですが、厳密なライブラリではcharです。文字の分類関数(tolowertoupperを除く、その前にある全て)の戻り値の型は、標準のライブラリではboolintですが、厳密なライブラリではboolです。ungetcへの第一引数の型は標準のライブラリではcharintですが、厳密なライブラリではchar型です(EOFungetcに渡すべきではない)。strchrstrrchrの第二引数は、標準のライブラリではcharintですが、厳密なライブラリではcharです。
  • グローバル変数、stdinstdoutstderrは、標準のライブラリではunchecked変数(Section 7.2参照)として宣言されています。厳密なライブラリではそれらはcheckedです。
  • グローバル変数errnoは、標準のライブラリではuncheckedで宣言されています。しかし、厳密なライブラリではcheckedstrictで宣言されています。

ライブラリのフラグが使用されていない場合、Splintは 標準のライブラリ、standard.lcd を読み込みます。 +nolibが設定されている場合、 どのライブラリも読み込まれません。 ライブラリのソースファイルは簡単に修正することが出来、 特定のアプリケーションにより適合するように 新しいライブラリを作成することが出来ます。

14.2 Generating Libraries(ライブラリの生成)

大規模なシステムでSplintの実行を可能とするため、 必要な情報を含むライブラリを生成するためのメカニズムが提供されています。 これは、ライブラリが作成された後、ソースファイルを独立してチェックすることが可能であることを 意味します。 コマンドラインのオプション-dump library でファイルlibrary(デフォルトの拡張子.lcdが追加される) の中に情報を格納します。 次に、-load libraryで、ライブラリを 読み込みます。 ライブラリには、ライブラリが作成されたときにチェックされたファイルからの インタフェース情報が含まれます。

14.2.1 Generating the Standard Libraries(標準ライブラリの生成)

標準ライブラリはSplintの配布物の中に含まれるヘッダファイルから生成されます。 いくつかのライブラリは複数のヘッダファイルから生成されます。 POSIXライブラリは、標準ライブラリを包含しているため、 標準ライブラリとPOSIXライブラリに対するヘッダはPOSIXライブラリ を作成するために結合されます。 同様に、UNIXライブラリは標準ヘッダ、POSIXヘッダ、そしてUNIXヘッダから 構成されています。 ヘッダファイルは、STRICT定義することにより 条件付で選択されるいくつかのセクションを含みます。 標準ライブラリを生成するためのコマンドは以下の通りです。

splint -nolib ansi.h -dump ansi
splint -nolib -DSTRICT ansi.h -dump ansistrict
splint -nolib ansi.h posix.h -dump posix
splint -nolib -DSTRICT ansi.h posix.h -dump posixstrict
splint -nolib ansi.h posix.h unix.h -dump unix
splint -nolib -DSTRICT ansi.h posix.h unix.h -dump unixstrict

14.3 Header File Inclusion(ヘッダーファイルのインクルード)

#include <X.h>

に遭遇したときのSplintの標準的な動作は、 インクルードファイルの検索パス(-Iを使用して設定される)と、 システムの基本インクルードパス(デフォルト値、通常/usr/includeが 設定、あるいは使用している場合、include環境変数から読み込まれる) 上で、X.hと名付けられたファイルを 検索することです。 X.hが 読み込まれた標準ライブラリにあるヘッダファイルの名前であり、かつ、 X.h がシステムディレクトリ(-sysdirsフラグで設定される。デフォルトは/usr/include)であるディレクトリ内で 発見される場合、+skip-iso-headersあるいは、 +skip-posix-headersX.hがISO あるいは POSIXのどちらのヘッダファイルなのかに依存する) がオン(両方ともデフォルトでオン)の場合、X.hはインクルードされません。 全てのヘッダが正常にインクロードされることを強制するには -skip-iso-headersフラグを使用してください。

時には、システムディレクトリ内にあるヘッダーに Splintでは解析できない標準ではない構文が含まれていることがあります。 +skip-sys-headersフラグは システムディレクトリ内のインクルードファイルがインクルードされないように するために使用されます。

Splintは中規模(10,000行)のプログラムを パフォーマンスを気にすることなく実行できるくらい十分速いです。 ライブラリは大規模なプログラム内で小さなモジュールの効率的なチェックを 可能とするために使用できます。 さらにパフォーマンスを向上させるために、ヘッダーファイルのインクルードを最適化することが出来ます。

たくさんのファイルが同じヘッダーをインクルードする 完全なシステムを処理する場合、処理時間の大部分は、必要の無い無駄な ヘッダーファイルの再読み込みです。 もし、100個のファイルからなるプログラムをチェックし、各ファイルが utils.hをインクルードしている場合、 Splintは(多くのCコンパイラも同じだろうが)utils.hを100回処理する必要があります。 もし、+single-includeフラグが使用されている場合、 各ヘッダーファイルは一度しか処理されません。 ヘッダーファイルの単一処理は、たくさんのファイルに分割された大規模なプログラムをチェックする際に 大幅な改善効果を生み出します。しかし、同じヘッダーファイルが 異なるコンテキストで常に同じ意味でインクルードされている場合しか安全ではありません (例えば、別のインクルード場所で、異なる定義で定義されたプリプロセッサ変数に依存しない)。

大規模システムにて1つのファイルを処理する場合、 時間の大部分はヘッダーファイルのインクルードの処理に費やされています。 ヘッダファイル内の情報が代わりにライブラリに格納されている場合、これを避けることが出来ます。 もし、+never-includeが設定されている場合、 .hで終わる ファイルのインクルードを防止することが出来ます。 異なる接尾辞を持つファイルは、通常は含まれます。 これを行うため、ヘッダーファイルは拡張されたマクロを含んではなりません。 つまり、ヘッダーファイルは+all-macrosで処理される必要があり、 ヘッダーファイル内の /*@notfunction@*/制御コメント は存在してはなりません。 それから、+never-includeフラグは ヘッダーファイルのインクルードを防止するために使用可能です。 あるいは、関数マクロではないマクロが、.h で終わらない名前で異なるファイルに移動することが出来ます。 ファイルから間接的にインクルードされる場合、.h が無視され、他のファイルが決してインクルードされないため、 このファイルは.c ファイルから直接インクルードされる必要があることを覚えてください。

これらのオプションは大規模システムで大幅なパフォーマンス 向上のために使用することが出来ます。 パフォーマンスはコードがどのように構造化されているのかに依存しますが、 ライブラリと+noincludeフラグが使用された場合、 大規模なプログラムの1つのモジュールのチェックは数倍速くなります。

14.3.1 Preprocessing Constants(プリプロセス時の定数)

Splintはソースファイルのプリプロセッサ時に、定数S_SPLINT_Sを定義しています。 もし、Splintを使用するときのみ、処理を行うコードを含めたい場合、 以下で囲んでください。

# ifdef S_SPLINT_S
...
# endif

このドキュメントはSplint(英)のサイトを元に作成しました