Type_safety
でコンピュータサイエンス、型の安全性はどの程度あるプログラミング言語の意欲や防止がエラーを入力します。タイプエラーは、プログラムの定数、変数、およびメソッド(関数)の異なるデータ型間の不一致によって引き起こされる誤ったプログラム動作です。たとえば、整数(int)を浮動小数点数(float)として扱います。より良い例が必要です。。型安全性は、プログラムが書かれている言語ではなく、コンピュータープログラムの特性であると考えられることもつまり、一部の言語には、同じ言語で他の型安全機能を使用するプログラマーが回避できる型安全機能が型安全性の正式な型理論的定義は、ほとんどのプログラマーが理解しているものよりもかなり強力です。
タイプエンフォースメントは静的で、コンパイル時に潜在的なエラーをキャッチするか、動的で、実行時にタイプ情報を値に関連付け、差し迫ったエラーを検出するために必要に応じてそれらを参照するか、または両方の組み合わせにすることができます。動的タイプエンフォースメントは本質的に無効なプログラムの実行を許可します。
特定のプログラミング言語によって型エラーとして分類される動作は、通常、適切なデータ型ではない値に対して操作を実行しようとした結果として生じる動作です。この分類は部分的に意見に基づいています。
静的(コンパイル時)型システムの文脈では、型の安全性は、通常、(とりわけ)いずれかの最終的な値であることを保証関係式は、その式の静的な型の正当なメンバーになりますが。正確な要件はこれよりも微妙です。たとえば、複雑化については、サブタイピングとポリモーフィズム(コンピューターサイエンス)を参照して
型安全性は、メモリの安全性と密接に関連しています。これは、あるメモリ位置から別のメモリ位置に任意のビットパターンをコピーする機能に対する制限です。たとえば、あるタイプの言語の実装では {t}
、(適切な長さの)ビットのシーケンスがの正当なメンバーを表さないように {t}
、その言語でデータをタイプの変数にコピーできる場合 {t}
、そのような操作は非を割り当てる可能性があるため、タイプセーフではありません {t}
その変数の値。逆に、言語が任意の整数をポインタとして使用できる程度に型安全でない場合、それはメモリ安全ではありません。
ほとんどの静的型付け言語は、メモリの安全性よりも厳密に強力な型の安全性を提供します。これは、型システムが、メモリの安全性やあらゆる種類の防止のために厳密に必要でない場合でも、プログラマーによって定義された抽象データ型の適切な使用を強制するためです。壊滅的な失敗の。
コンテンツ
1 定義
2 他の形態の安全との関係
3 タイプセーフおよびタイプセーフでない言語
4 強いタイピングと弱いタイピング
5 オブジェクト指向言語での型安全性
6 特定の言語でのタイプの安全性の問題
6.1 エイダ 6.26.3 C ++ 6.4 NS# 6.5 Java 6.6 標準ML 6.7 Modula-2 6.8 パスカル 6.9 Common Lisp
7 C ++の例
8 も参照してください
9 ノート
10 参考文献
定義
タイプセーフコードは、アクセスが許可されているメモリ位置にのみアクセスします。(この説明では、型安全性は具体的にはメモリ型安全性を指し、より広い意味で型安全性と混同しないで)たとえば、型安全コードは別のオブジェクトのプライベートフィールドから値を読み取ることはできません。
ロビンミルナーは、型安全性を説明するために次のスローガンを提供しました。
よくタイプされたプログラムは「うまくいかない」ことはできません。
このスローガンの適切な形式化は、特定の言語で使用される形式的なセマンティクスのスタイルによって異なります。表示的意味論の文脈では、型安全性とは、たとえば型τで適切に型付けされた式の値が、τに対応する集合の善意のメンバーであることを意味します。
1994年に、AndrewWrightとMatthiasFelleisenは、操作的意味論によって定義された言語での型安全性の標準的な定義と証明手法を策定しました。このアプローチでは、型の安全性はプログラミング言語のセマンティクスの2つのプロパティによって決定されます。(タイプ-)保存または
主題の削減
プログラムの「適切な型付け」(「型付け可能性」)は、言語の遷移規則(つまり、評価規則または削減規則)の下では不変のままです。
進捗
適切に型指定された(入力可能な)プログラムが「スタック」することはありません。つまり、プログラム内の
式が値に評価されるか
、その遷移規則がつまり、プログラムが未定義の状態になり、それ以上の遷移が不可能になることはありません。
これらの特性は真空中には存在しません。それらは、それらが記述するプログラミング言語のセマンティクスにリンクされており、「適切に型指定された」プログラムの概念はプログラミング言語の静的セマンティクスの一部であり、概念であるため、これらの基準に適合するさまざまな言語の大きなスペースが 「行き詰まる」(または「うまくいかない」)のは、その動的セマンティクスのプロパティです。
Vijay Saraswatは、次の定義を提供します。
「言語のデータに対して実行できる操作が、データのタイプによって認可された操作のみである場合、その言語はタイプセーフです。」
他の形態の安全との関係
型安全性は、最終的には他の問題を排除することを目的としています。例:-
違法行為の防止。たとえば3 / “Hello, World”、算術の規則では整数を文字列で除算する方法が指定されていないため、式を無効として識別できます。
メモリの安全性
ワイルドポインタは、あるタイプのオブジェクトへのポインタが別のタイプへのポインタとして扱われる場合に発生する可能性がたとえば、オブジェクトのサイズはタイプによって異なるため、間違ったクレデンシャルでポインタがインクリメントされると、メモリのランダムな領域を指すことになります。
バッファオーバーフロー-範囲外の書き込みは、ヒープにすでに存在するオブジェクトの内容を破壊する可能性がこれは、あるタイプの大きなオブジェクトが別のタイプの小さなオブジェクトに大まかにコピーされた場合に発生する可能性が
さまざまなタイプのセマンティクスに起因する論理エラー。たとえば、インチとミリメートルは両方とも整数として格納できますが、相互に置き換えたり、追加したりしないで型システムは、2つの異なるタイプの整数を強制できます。
タイプセーフおよびタイプセーフでない言語
型安全性は通常、アカデミックプログラミング言語の研究で提案されているおもちゃの言語の要件です。一方、多くの言語は、何千ものケースをチェックする必要があるため、人間が生成した型安全性の証明には大きすぎます。それにもかかわらず、厳密に定義されたセマンティクスを持つStandard MLなどの一部の言語は、型安全性の1つの定義を満たすことが証明されています。のようないくつかの他の言語Haskellのはされていると思わ提供される特定の「エスケープ」の特徴は、(例えばHaskellの使用されていない、型の安全性のいくつかの定義を満たすためにunsafePerformIOでI通常の制限された環境からの「脱出」を使用し、 / Oは可能であり、型システムを回避するため、型の安全性を破るために使用できます。)型のパンニングは、このような「エスケープ」機能のもう1つの例です。言語定義のプロパティに関係なく、実装または他の言語で記述されたリンクライブラリのバグが原因で、実行時に特定のエラーが発生する場合がこのようなエラーは、特定の状況で特定の実装タイプを安全でなくなる可能性がSunのJava仮想マシンの初期バージョンは、この種の問題に対して脆弱でした。
強いタイピングと弱いタイピング
強いタイピングと弱いタイピング
プログラミング言語は、型の安全性の特定の側面を参照するために、口語的に強い型または弱い型(また緩く型付けされている)として分類されることがよく1974年、LiskovとZillesは、強い型の言語を「オブジェクトが呼び出し元の関数から呼び出された関数に渡されるときはいつでも、その型は呼び出された関数で宣言された型と互換性がなければならない」と定義しました。 1977年、ジャクソンは、「強く型付けされた言語では、各データ領域は異なる型を持ち、各プロセスはこれらの型に関して通信要件を述べます」と書いています。対照的に、弱い型の言語は、予測できない結果を生成したり、暗黙的な型変換を実行したりする可能性が
オブジェクト指向言語での型安全性
では、オブジェクト指向言語型の安全性があるという事実に、通常は固有のものである型システムが整備されています。これは、クラス定義の観点から表現されます。
クラスは、本質的にそれから誘導されるオブジェクトの構造と定義するAPIとして契約、これらのオブジェクトを処理するために。新しいオブジェクトが作成されるたびに、そのオブジェクトはそのコントラクトに準拠します。
特定のクラスから派生したオブジェクトを交換する、または特定のインターフェイスを実装する各関数は、そのコントラクトに準拠します。したがって、その関数で許可される操作は、オブジェクトが実装するクラスのメソッドによって定義された操作のみになります。これにより、オブジェクトの整合性が維持されることが保証されます。
これに対する例外は、オブジェクト構造の動的な変更を可能にするオブジェクト指向言語、またはクラスメソッド定義によって課せられる制約を克服するためにオブジェクトのコンテンツを変更するためのリフレクションの使用です。
特定の言語でのタイプの安全性の問題編集
エイダ
ウィキブックスのAdaプログラミングには、次のトピックに関するページが型システム
Adaは、組み込みシステム、デバイスドライバー、およびその他の形式のシステムプログラミングに適しているだけでなく、タイプセーフなプログラミングを促進するように設計されています。これらの相反する目標を解決するには、エイダは、名前を通常の文字列で始まる特殊な構造の特定のセットにタイプ-危難を閉じ込める
Unchecked_。Unchecked_Deallocationは、プラグマPureをこのユニットに適用することにより、Adaテキストのユニットから効果的に禁止できます
。プログラマーは、必要な場合にのみ、Unchecked_構文を非常に注意深く使用することが期待され
ます。それらを使用しないプログラムはタイプセーフです。
SPARKプログラミング言語を同時に添加しながら、そのすべての潜在的なあいまいさや不安を解消するエイダのサブセットであり、静的にチェックする契約を言語には利用できます。SPARKは、実行時の割り当てを完全に禁止することにより、ダングリングポインタの問題を回避します。
Ada2012は、静的にチェックされたコントラクトを言語自体に追加します(事前条件、事後条件、および型の不変条件の形式で)。
NS
ウィキブックスには、Cプログラミングに関する本が
Cプログラミング言語は、限られた状況でタイプセーフです。たとえば、明示的なキャストが使用されていない限り、あるタイプの構造体へのポインタを別のタイプの構造体へのポインタに変換しようとすると、コンパイル時エラーが生成されます。ただし、非常に一般的な操作の多くはタイプセーフではありません。たとえば、整数を出力する通常の方法は、のようなものprintf(“%d”, 12)で、実行時に整数引数を期待するように%d指示printfします。(printf(“%s”, 12)文字列へのポインターを期待し、整数引数を提供するように関数に指示するのようなものは、コンパイラーによって受け入れられる可能性がありますが、未定義の結果を生成します。)これは一部のコンパイラー(gccなど)のチェックによって部分的に軽減されます。 printf引数とフォーマット文字列の間の型の対応。
さらに、Cは、Adaと同様に、未指定または未定義の明示的な変換を提供します。Adaとは異なり、これらの変換を使用するイディオムは非常に一般的であり、Cにタイプの危険な評判を与えるのに役立ちました。たとえば、ヒープにメモリを割り当てる標準的な方法mallocは、必要なバイト数を示す引数を使用して、などのメモリ割り当て関数を呼び出すことです。この関数は、型指定されていないポインター(type void *)を返します。これは、呼び出し元のコードが明示的または暗黙的に適切なポインター型にキャストする必要がCの事前に標準化された実装では、そうするために明示的なキャストが必要だったため、コードは受け入れられた慣習になりました。(struct foo *) malloc(sizeof(struct foo))
C ++
よりタイプセーフなコードを促進するC ++のいくつかの機能:
新しい一方オペレータは、オペランドに基づくタイプのポインタを返すmalloc関数は、ボイドのポインタを返します。
C ++コードは、仮想関数とテンプレートを使用して、voidポインターなしでポリモーフィズムを実現できます。
実行時型チェックを実行する動的キャストなど、より安全なキャスト演算子。
C ++ 11の強い型の列挙型は、整数または他の列挙型との間で暗黙的に変換することはできません。
C ++の明示的なコンストラクターとC ++ 11の明示的な変換演算子は、暗黙的な型変換を防ぎます。
NS#
C#はタイプセーフです(ただし、静的にタイプセーフではありません)。型指定されていないポインタをサポートしていますが、コンパイラレベルで禁止できる「unsafe」キーワードを使用してアクセスする必要がランタイムキャスト検証を本質的にサポートしています。キャストは、キャストが無効な場合にnull参照を返す「as」キーワードを使用するか、キャストが無効な場合に例外をスローするCスタイルのキャストを使用して検証できます。CSharp変換演算子を参照して
オブジェクトタイプ(他のすべてのタイプの派生元)に過度に依存すると、C#タイプシステムの目的を損なうリスクが通常、C ++のテンプレートやJavaのジェネリックと同様に、ジェネリックを優先してオブジェクト参照を破棄することをお勧めします。
Java
ウィキブックスには、Javaプログラミングに関する本が
Java言語は、型の安全性を強化するために設計されています。Javaで何が起こるの内部オブジェクト、各オブジェクトは、インスタンスであるクラス。
型安全性の強制を実装するには、使用する前に、各オブジェクトを割り当てる必要がJavaではプリミティブ型の使用が許可されていますが、適切に割り当てられたオブジェクト内でのみ使用できます。
型安全性の一部が間接的に実装される場合がたとえば、クラスBigDecimalは任意精度の浮動小数点数を表しますが、有限表現で表現できる数のみを処理します。演算BigDecimal.divide()は、BigDecimalとして表される2つの数値の除算として新しいオブジェクトを計算します。
この場合、たとえば1/3 = 0.33333 …を計算するときのように、除算に有限表現がない場合、演算に丸めモードが定義されていないと、divide()メソッドで例外が発生する可能性がしたがって、言語ではなくライブラリが、オブジェクトがクラス定義に暗黙的に含まれるコントラクトを尊重することを保証します。
標準ML
ウィキブックスには、次のトピックに関する本が標準MLプログラミング
Standard MLは厳密に定義されたセマンティクスを持ち、タイプセーフであることが知られています。ただし、New Jerseyの標準ML(SML / NJ)、その構文バリアントMythrylおよびMLtonを含む一部の実装は、安全でない操作を提供するライブラリを提供します。これらの機能は、特定の方法でレイアウトされたデータを必要とする可能性のある非MLコード(Cライブラリなど)と対話するために、これらの実装の外部関数インターフェイスと組み合わせて使用されることがよくもう1つの例は、SML / NJインタラクティブトップレベル自体です。これは、ユーザーが入力したMLコードを実行するために安全でない操作を使用する必要が
Modula-2
Modula-2は、安全でない施設を安全でないものとして明示的にマークすることを要求する設計哲学を持つ強い型の言語です。これは、そのような機能を、使用する前にインポートする必要があるSYSTEMと呼ばれる組み込みの疑似ライブラリに「移動」することによって実現されます。したがって、インポートにより、そのような機能が使用されたときに表示されます。残念ながら、これは元の言語レポートとその実装では結果的に実装されませんでした。事前のインポートなしで使用できる、型キャスト構文やバリアントレコード(Pascalから継承)などの安全でない機能がまだ残っていました。これらの機能をSYSTEM疑似モジュールに移動することの難しさは、識別子のみをインポートでき、構文はインポートできないため、インポートできる機能の識別子がないことでした。
輸入 システム; (*特定の危険な機能の使用を許可します:*)VAR ワード : SYSTEM 。WORD ; addr : SYSTEM 。住所; addr := SYSTEM 。ADR (単語);(*ただし、型キャスト構文はそのようなインポートなしで使用できます*)VAR i : INTEGER ; n : CARDINAL ; n := CARDINAL (i ); (*または*) i := INTEGER (n );
ISO Modula-2標準は、型キャスト構文を疑似モジュールSYSTEMからインポートする必要があるCASTと呼ばれる関数に変更することにより、型キャスト機能に対してこれを修正しました。ただし、バリアントレコードなどの他の安全でない機能は、疑似モジュールSYSTEMからインポートしなくても利用できます。
輸入 システム; VAR i : INTEGER ; n : CARDINAL ; i := SYSTEM 。CAST (INTEGER 、 n ); (* ISO Modula-2で型キャスト*)
言語の最近の改訂は、元の設計哲学を厳密に適用しました。まず、疑似モジュールSYSTEMの名前がUNSAFEに変更され、そこからインポートされた施設の危険な性質がより明確になりました。次に、残りのすべての安全でない施設(たとえば、バリアントレコード)が完全に削除されるか、疑似モジュールUNSAFEに移動されます。インポートできる識別子がない施設のために、有効化識別子が導入されました。このような機能を有効にするには、対応する有効化識別子を疑似モジュールUNSAFEからインポートする必要がUNSAFEからのインポートを必要としない言語で安全でない施設は残っ
IMPORT UNSAFE 。VAR i : INTEGER ; n : CARDINAL ; i := 安全ではありません。CAST (INTEGER 、 n ); (* Modula-2 Revision 2010で型キャスト*)FROM UNSAFE IMPORT FFI 。 (*外部関数インターフェース機能の識別子を有効にする*) (* Cへの外部関数インターフェースのプラグマ*)
パスカル
ウィキブックスには、Pascalプログラミングに関する本が
Pascalにはいくつかの型安全性要件があり、そのうちのいくつかは一部のコンパイラーに保持されています。Pascalコンパイラが「厳密な型付け」を指示する場合、互換性があるか(整数から実数への変換など)、または同じサブタイプに割り当てられていない限り、2つの変数を相互に割り当てることはできません。たとえば、次のコードフラグメントがある場合:
タイプ TwoTypes = レコード I : 整数;
Q : 本物; 終了; DualTypes = レコード I : 整数; Q : 本物; 終了;var T1 、 T2 : TwoTypes ; D1 、 D2 : DualTypes ;
厳密なタイプの下で、のように定義された変数
TwoTypesがある互換性がないと
DualTypes(これらはそのユーザー定義型の構成要素は同一であっても、同一ではないため)との割り当て
{{{1}}}は違法です。{{{1}}}の割り当ては
、それらが定義されているサブタイプが同一であるため、正当です。ただし、{{{1}}}などの割り当て
は有効です。
Common Lisp
一般的に、CommonLispはタイプセーフな言語です。Common Lispコンパイラは、型の安全性を静的に証明できない操作の動的チェックを挿入する役割を果たします。ただし、プログラマーは、プログラムをより低いレベルの動的型チェックでコンパイルする必要があることを示す場合がこのようなモードでコンパイルされたプログラムは、タイプセーフとは見なされません。
C ++の例
次の例は、C ++キャスト演算子が誤って使用された場合に型安全性を破ることができる方法を示しています。最初の例は、基本的なデータ型を誤ってキャストする方法を示しています。
#include 名前空間stdを使用します; int main (){
int ival = 5 ; //整数値フロートFVAL = reinterpret_castは (IVAL )。//ビットパターンを再解釈しますcout 次の例は、オブジェクト参照が誤ってダウンキャストされる方法を示しています。
#include 名前空間stdを使用します; クラス 親{ パブリック: 仮想〜親(){} // RTTIの仮想デストラクタ}。 クラス Child1 :public Parent { パブリック: int a ; };クラス Child2 :public Parent { パブリック: フロートb ; };int main (){
Child1 c1 ; c1 。a = 5 ;
親&p = c1 ; //常に安全なアップキャストChild2 &c2 = static_cast (p ); //無効なダウンキャストcout
も参照してください
型理論
ノート
^ Milner、Robin(1978)、「プログラミングにおける型多型の理論」、Journal of Computer and System Sciences、17(3):348–375、doi:10.1016 / 0022-0000(78)90014-4 ^ サラスワット、ビジェイ(1997-08-15)。「Javaはタイプセーフではありません」。
^ 標準ML。Smlnj.org。2013-11-02に取得。
^ 「System.IO.Unsafe」。GHCライブラリマニュアル:base-3.0.1.0。2008年7月5日にオリジナルからアーカイブされました。
^ リスコフ、B; Zilles、S(1974)。「抽象データ型を使用したプログラミング」。ACMSIGPLANの通知。9(4):50–59。CiteSeerX 10.1.1.136.3043。土井:10.1145 /942572.807045。 ^ ジャクソン、K。(1977)。並列処理とモジュラーソフトウェアの構築。プログラミング言語の設計と実装。コンピュータサイエンスの講義ノート。54。pp。436–443。土井:10.1007 / BFb0021435。ISBN 3-540-08360-X。
^ 「CS1130。オブジェクト指向プログラミングへの移行。– 2012年春-セルフペースバージョン」。コーネル大学、コンピュータサイエンス学部。2005年からアーカイブオリジナルの2005年。取得した2015年11月23日を。
^ したがって、型の安全性もクラス定義の問題です。オブジェクトの内部状態を変更するパブリックメソッドは、オブジェクトの反復性を保持する必要が ^ カーニハン; デニス・M・リッチー(1988年3月)。Cプログラミング言語(第2版)。ニュージャージー州エングルウッドクリフ:プレンティスホール。NS。 116。ISBN 978-0-13-110362-7。Cでは、適切なメソッドは、mallocがvoidへのポインターを返すことを宣言してから、キャストを使用してポインターを目的の型に明示的に強制することです。
^ ニクラウス・ヴィルト(1985)。Modula-2でのプログラミング。シュプリンガーバーラグ。
^ 「安全と安全ではない施設の分離」。取得した3月24日に2015。
^ 「ISOModula-2言語リファレンス」。取得した3月24日に2015。
^ 「CommonLispHyperSpec」。検索された26 5月2013。
^ http://en.cppreference.com/w/cpp/language/reinterpret_cast ^ http://en.cppreference.com/w/cpp/language/dynamic_cast
参考文献
ピアス、ベンジャミンC.(2002)。タイプとプログラミング言語。MITプレス。ISBN 978-0-262-16209-8。
「タイプセーフ」。ポートランドパターンリポジトリWiki。
ライト、アンドリューK。; Matthias Felleisen(1994)。「タイプの健全性への構文的アプローチ」。情報と計算。115(1):38–94。土井:10.1006 /inco.1994.1093。
Macrakis、Stavros(1982年4月)。「安全とパワー」。ACMSIGSOFTソフトウェアエンジニアリングノート。7(2):25–26。土井:10.1145 /1005937.1005941。S2CID 10426644。