すべての言語に意味的および論理的なエラーがある可能性はありますか?


7

私はPHPについて読んでおり、多くの著者がセマンティックエラーと論理エラーを別々に言及しています。セマンティックエラーの例として、不正な数のパラメーターで呼び出される関数が提供されます。これはパーサーによってキャッチされませんが、実行時にエラーをスローします。

しかし、C ++などの言語では、これはコンパイラーによってキャッチされます。その時それは構文エラーだと思います。意味的エラーと論理的エラーの違いは何ですか?

たとえば、「コンピュータサイエンティストのように考える方法」では、著者は「論理エラー」と「意味エラー」を同じ意味で使用しています。一方、Visual Basic .NETでは。Primer Plusでは、「論理エラー」は「セマンティックエラー」から分離されています。



私は定義を知っています、問題は回答で述べられているように、すべてのプログラミング言語に同じように適用されるわけではないということです。意味、構文、論理のエラーは何であるかは尋ねませんでした。一部の作成者は、セマンティックを論理エラーであると考えていますが、そうでない場合もあります。

1
間違った引数で関数を呼び出すことは、構文エラーではありません。これはタイプであり、したがって意味上のエラーです。

一部の人々は、「構文」という用語に静的セマンティクス(名前、型など)を含め、コンパイラによって「構文」としてチェックできる(またはむしろ)チェックできるすべてのものを効果的に示します。「セマンティック」とは、動的メソッドのディスパッチなど、プログラムの実行を制御するものです。「論理的誤り」の正式な定義を知りません。たぶん、あなたは間違い、障害、エラーを区別したいでしょう。(プログラマーによる)論理的誤りは(プログラム内で)障害を引き起こし、コンパイラーが除外できない(実行時に)エラーを引き起こす可能性があります(NPE、div-by-zeroなど)。
ラファエル

回答:


7

私は、交換可能に、「論理エラー」と「セマンティックエラー」を使用して、いくつかの作家との区別を描くいくつかの作家のための説明は、彼らがいないということだけである可能性が高いと考えてい人々が若干異なる用語を使用しているので、正確な普遍的に受け入れられている定義を、と。私はそれに夢中にならないでしょう。

「ロジック」と「セマンティック」はどちらもプログラミングの意味と関係があることを意味しているため、それらを同じものと見なすのは簡単です。

私が区別を付けるとしたら、私が見ることができる有用な1つは、論理エラーはプログラムがプログラマーの意図とは異なる何かを意味するようになり、意味エラーはプログラムが何も意味を持たなくなる(一貫性がある)ことです。まったく。これらの定義を使用して、論理エラーをセマンティックエラーのスーパーセットと見なすか、その論理エラーによってプログラムの不整合を引き起こすエラーを除外できます。

たとえば、次の疑似コードには論理エラーのみが含まれています。

x = read_number_from_user("x: ")
y = read_number_from_user("x: ")
print("The product of x and y is: ")
print(stringify(x + y))

このプログラムの意味(現状のままで、プログラマーの意図を考慮せずに取得)は、完全に単純で一貫しています。しかし、それはプログラマが意図したことを意味するものではありません。

OTOH、次の疑似コードにはセマンティックエラーが含まれています。

name = read_string_from_user("What is your name?")
print(name + 1)

少なくとも、文字列と数値を追加しても何の意味もないと想定している場合はそうです。PHPのような言語でそれ何かを意味し、これは意味上のエラーではありません。

誤った数のパラメーターを使用して関数を呼び出すというPHPのセマンティックエラーの例は、そのセマンティックエラーを呼び出す必要があるかどうか(私が使用している定義を使用して)を検討する必要があるため、実際には興味深いものです。

関数は、PHPで実行時に動的に定義されます。したがって、不正な数のパラメーターを使用して関数を呼び出すと、論理エラーと見なされる可能性があります。おそらく間違ったincludeステートメントが実行されたため、同じ名前の別の関数が、呼び出しの宛先とは異なる関数に含まれていました。そうでない場合でも、間違った数の引数を使用して関数を呼び出すことは、何かを意味します。これは、この名前で関数を検索し、これらの引数を渡すことを意味します。インタプリタがこれらのリクエストを実行できないことが判明したのは、実行時にのみ操作上です。ちょうどx / y何かを意味yしますが、実行時にたまたま0になると実行できない場合があります。

最終的に、ここで私が論理エラーと意味的エラーを区別するような分類を使用してエラーをどのように分類するか(それが正確に私のエラーではない場合でも)は、話している特定の言語と方法によって大きく異なります言語でプログラムに意味を割り当てます。最も一般的に使用される言語に、プログラムに意味を割り当てるための標準的な方法ありません。つまり、誰もがわずかに異なる方法を使用します(ただし、誰もが解釈すると、ほとんどすべての運用上の影響に非常に密接に同意ます)。 "と"セマンティック "の違いは異なります。

もう1つの同様の見方は、セマンティックエラーはプログラミング言語がプログラムを無効として拒否する原因であると言うことです(構文エラーは別として、必要に応じてこれらのセマンティックエラーのサブセットを呼び出すことができます)。プログラミング言語がプログラムを受け入れる場合、それは何かを意味し、実行時に失敗する場合、それは論理エラーの結果です。これは、プログラムが何を意味するかの定義として、プログラミング言語の実装(インタプリタ、コンパイラ+ランタイムシステムなど)をほとんど割り当てています。


3

プログラムのエラーの多くのカテゴリは、それらが現れる場所に基づいて区別することができます。一部のカテゴリは、特定のコンテキストでは発生しません(プログラミング言語、プログラムの設計方法、プログラムの使用方法によって異なります)。用語はコミュニティによって大きく異なります。主なカテゴリーの類型を示します。それを念頭に置いて

  • これらのカテゴリの一部が適用されないワークフローがあります。
  • 他の区別をするのに便利なワークフローがあります。
  • 使用されるプログラミング言語とツールによっては、同様のエラーが異なるカテゴリに分類される場合があります。
  • 人によって用語は異なります。私が付けた名前はもっともらしいですが、決して同意しているわけではありません。

エラーが発生した時点に基づいて、さまざまなカテゴリのエラーを区別できます。

  1. 構文エラー
    コンパイラーまたはインタープリターは、作成した内容が意味をなさないことを通知します。ほとんどの言語では、これは致命的なエラーであり、プログラムの実行を開始することさえできません。
    例:閉じ括弧がない。

  2. 静的型エラーとその他のコンパイラエラー
    コンパイラまたはインタープリタは、要求された内容を理解しているが、それは意味をなさないことを示しています。構文エラーと他の種類のコンパイラエラーの違いは、内部コンパイラ設計の問題、または場合によってはプログラミング言語の設計の問題です。
    例:定義されていない変数を使用する(これは多くの場合、構文エラーと見なされますが、常にではありません)

    静的に型付けされた言語では、コンパイラはある種の無効な操作を試みるプログラムを拒否します。動的に型付けされた言語では、このようなエラーは、致命的かどうかにかかわらず、実行時エラーです。例:整数を文字列で除算しようとしています。

  3. 起動エラー
    これは、プログラムを作成した人ではなく、プログラムを実行した人に明らかにされる最初のエラーのカテゴリです。
    プログラムが起動しないか、プログラムが実際に何かを実行する状態になりません。
    例:システムに存在しない外部ライブラリを使用しようとしています。
    例:インタープリター言語での構文エラーまたはコンパイルエラー(プログラマーがソースコードを配布する場所)。

  4. 致命的なランタイムエラー
    ある時点で、プログラムは動作を停止します。
    例:メモリアクセス違反(プログラムに割り当てられていないメモリへのアクセスの試み)
    十分に複雑なプログラムは、エラーを検出しようとして、回復可能なエラーに変わる可能性があることに注意してください。

  5. 予期しないが回復可能なランタイムエラー
    プログラムの一部のコンポーネントが動作を停止しますが、プログラムは続行します。例:メモリ不足(プログラムがこれを適切に処理するように設計されている場合)
    例:マルチプロセスアプリケーションの1つのプロセスがクラッシュするが、他のプロセスは実行し続ける

  6. 予期される実行時エラー
    いくつかのエラー状態が予想されますが、プログラムされています。これは通常の動作であり、「悪い」とはいえ、発生する可能性のある外部イベントに反応します。プログラム全体として考えると、これらは実際にはエラーではありません。
    例:ファイルが見つかりません
    例:ネットワーク切断
    例:無効なユーザー入力

  7. プログラミングエラー
    プログラムは何かを実行していますが、それはその仕様に従ってそれが実行することになっていることではありません。プログラマーが意図したことと、ソースコードが実際に意味することには違いがあります。
    例:Webアプリケーションではファイルをアップロードできるはずですが、スペースを含むファイル名では機能しません。アプリケーションはファイルを拒否し、作業を続けます。
    例:ある数値を乗算するように設計されたプログラムが結果を返しますが、数学演算が正しく実行されていません。

  8. 仕様エラー
    プログラムは何らかの処理を行っており、仕様またはドキュメントに準拠しています。ただし、反映すると、この状況でのプログラムの動作は良くありません。(もちろん、「良くない」は主観的な判断です。)
    例:コンポーネント1は、スペースで区切られたファイル名のリストを想定しています。コンポーネント2は、スペースを含む単一のファイル名を送信します。2つのコンポーネントは、連携するように注意深く設計されていません。
    例:天候を予測するプログラムは、物理的な世界のモデリングが十分ではなかったため、降らない雨を発表します。

2–4を意味的エラーと見なし、7–8を論理エラーと見なすことは、かなり一般的です。(ただし、用語は異なる場合があります。)回復可能な実行時エラーは、プログラム全体のエラーではなく、一部の実行時エラーと見なされる場合があります。

それを考慮した別の用語があります

  • セマンティックエラーとは、静的型システムを備えたコンパイラが通常キャッチするもの、または「保護」ランタイムシステムが外部イベントに起因しない例外(たとえば、ファイルではなくメソッドが見つからない)でプログラムを異常終了させるものです見つかった);
  • 論理エラーはキャッチされないものです。

これは、特定の言語と特定の型チェッカーを考えると、かなり正確な違いになる可能性があります。しかし、人々がこれらの用語を使用するとき、彼らはその仮想コンパイラがどうなるかについて非常に不正確な考えを持っていることがよくあります。たとえば、Javaでプログラミングしている場合、間違った数の引数を渡すとコンパイラによってキャッチされます。PHPでプログラミングしている場合、それはランタイムシステムによって捕捉されます。Perlでプログラミングしている場合は、キャッチされない可能性があります(引数宣言がない場合、余分な引数は無視され、欠落している引数はデフォルト値を生成します)。

または、別の例として、10要素の配列があり、11番目の配列にアクセスしようとしているとします。Cなどの一部の言語では、これによりプログラムがメモリの無関係なゾーンにアクセスし、予測できない動作が発生します。他の言語では、これにより例外がスローされます。プログラマーがこれを予期したかどうかに応じて、これはセマンティックエラー(プログラマーはインデックスが範囲外であることを予期していたが、その状況をチェックしなかった)、論理エラー(プログラマーはインデックスが常に有効であると誤って考えた) )、またはまったくエラーではありません(プログラマは、配列のインデックスが配列の境界内にあるかどうかをテストするために例外に依存していました)。

この話の教訓は、これらの分類は非常に変動しやすいということです。どのエラーがどの作成者によってどのカテゴリに分類されるかについては、あまり重要視しないでください。重要なことは、あなたが書くこととプログラムが何をすべきかの間の関係を理解することです。プログラマーとしてのあなたの仕事は、私が書いたこと私が言っていることの間に大きなギャップをもたらすことです。ギャップに何かが落ちた場合、ラベルを付けることにこだわらないでください。何がうまくいかず、どのように修正するかを理解することに集中します。


「あなたが書いたものは意味をなさない」vs「それは意味をなさない」は明確な区別ではありません。「CFGの解析に失敗しました->構文エラーです。残りの部分(コンパイラー内)->静的セマンティクス」と言った方がいいと思います。さらに、私は答えが間違い、障害、エラーの区別から利益を得ると思います(質問へのコメントで説明/定義したように)。
ラファエル

エラータイプの区別は、特定のプロジェクトのプログラミング言語を選択するのに役立ちます。一部の環境(たとえば、セキュリティの重要なシステム)では、可能な限り多くのエラーを確実に除外するために、コンパイラーができる限り多くの間違いをキャッチしたい場合があります。この目的のために、(単純な)正式な仕様を理解して検証するコンパイラさえあります(「論理的な間違い」をキャッチします)。
ラファエル

1

基本的には、まず言語自体を調べる必要があります。

PHPはインタープリター言語です。つまり、スクリプトは実行時に毎回コンパイルされて実行されます。C++はコンパイラー言語です。つまり、スクリプトはビルド時にコンパイラーで1回コンパイルされ、その後実行できます。

そのため、両方のコンパイラが例からのセマンティックエラーを認識しますが、phpコンパイラは実行時にこれを行い、c ++コンパイラはコンパイル時にこれを行います。

あなたの質問の良い説明はウィキペディアここにあります(意味と構文の違い)


これは間違いです。通常、PHPもコンパイルされ、オペコードキャッシュを使用すると、そのコンパイルフェーズは実行フェーズから分離されます。違いの本当の理由は、C ++がPHPよりもはるかに強力な型指定と型チェックを使用することです。確かに、強い型付けと個別のコンパイルは通常一緒に行われますが、厳密に言えば、そうする必要はありません。
reinierpost 2014年

0

私の推測:

  • セマンティック(AL)エラーが構文的に有効であるコードを生成し、プログラミングのミスですが、おそらくそのプログラマが意図したものを行うことができない、という意図が何であったかに関係なく。コードは間違いなく間違っており、ソフトウェアツールによってフラグが付けられている可能性があります。ただし、ソフトウェアツールはそのようなエラーすべてにフラグを付けることはできません(ライスの定理による)。
  • ロジック(AL)エラーは、プログラマが異なる意図を持っていた場合、それは正しいされているかもしれないが、構文的に有効であるコードを生成し、プログラミングのミスですが、そのプログラマの意図に行いません。コードが間違っているのは、プログラマーの意図があった場合のみです。ソフトウェアツールはコードに誤ったフラグを付けることはできません。できる限り、この間違いの可能性を示唆しています。

0

プログラムは、データに関する質問に答える結果の計算を表現することを目的としたテキストです。たとえば、並べ替えプログラムは値のリスト(データ)を取得し、同じ値の別のリストである結果を計算しますが、いくつかの比較関数に従って並べ替えられます。

このテキストは、正当なプログラムテキストの構成要素と、このテキストに計算上の意味を関連付ける方法の両方について、正確に定義された(または定義する必要がある)ある種の言語で正式に表現されます。このような正確な定義は、多くの場合抽象的(おそらく数学的)であり、コンピューターの制限などの具体的な問題を無視することがあります。

しかし、その後、プログラムを実行できるように言語が実装されます。元のプログラムテキストのインタプリタを使用するか、いくつかの中間コード(たとえば、バイトコード)にコンパイルしてから、この中間コードを解釈するか、それをさらにマシンコードにコンパイルする可能性があります。そして、他のバリエーションがあるかもしれません。そしてもちろん、コンパイラやインタプリタを書く方法はたくさんあり、それらを実行するマシンもたくさんあります。

さらに、いくつかの正式な定義と、うまくいけば一貫性のあるいくつかの実装があるかもしれません。

エラーは、正式な定義または実装の一方または両方の構造に関連して分類できます。ただし、使用されなくなった古い参照実装に従ってエラーが分類されるという奇妙な状況が発生する可能性があります。

これは基本的に、エラーの分類があまり安定したトピックではないことを意味します。さらに、一部の言語では、何かが間違いなく間違っている(プログラムが実行されない)か、推奨されていないことを行っているかによって、いくつかのレベルのエラーが区別される場合がありますが、それでもある程度の計算が行われます。これは、例外などのプログラミング言語の機能にも反映されており、リカバリーできる場合とできない場合があります。

標準的な違いは次のとおりです。

構文エラー:与えられたテキストは、それが何を意味するかに関係なく、プログラムテキストの構造に適合していません。これは、通常はコンテキストフリーの正式な言語構文のみを指す場合があります。場合によっては、さらに進んで、変数宣言(存在する場合)や型の整合性などのいくつかの基本機能のチェックが含まれることもありますが、これらはセマンティックエラーと見なされることもあります。

意味的または論理的なエラー:これらは、プログラムを実際に実行するときに検出できるエラーです。これは、プログラムがゼロで除算したり、配列にインデックスを付けたりしないなど、意味論上意味のない計算が実行されるためです。境界。間違った数の引数、または間違った型の引数で関数を呼び出すことも、意味上のエラーと見なされる場合があります。一部の言語では、エラーは実際には例外によってユーザー定義である場合があります。エラーは、プログラムの一部でユーザー定義のより高いレベルのセマンティクスに対応している場合です(例外の他の用途もあります)。これらのエラーのいくつかは、実行時に検出されるため、ランタイムエラーとも呼ばれますが、ハードウェア制限エラーと混同しないでください。

ハードウェア制限エラー:これらは、実装が制限のある実際のマシン上にあるという事実によるエラーです。たとえば、これはメモリワードに収まりきらないほどの整数、またはデータ構造を作成するための十分なメモリがない可能性があります。これらは通常、実行時にも検出されます。

セマンティックエラーとハードウェア制限エラーに関して、静的セマンティック分析と呼ばれるものを使用して、プログラムを実行する前にそれらを検出できる場合があります。。これは、宣言や初期化されていない変数、タイプエラー、ゼロによる除算や配列の境界チェックの場合によく見られますが、さらに進んでいる場合があります。静的セマンティック分析は、多くの最適化手法のコンパイラーでも重要です。多くの場合、静的セマンティクスと動的セマンティクスは分離されています。私が想像できる最高の定義は、静的セマンティクスが、実際のデータがなくてもコンパイル時に決定可能なプロパティに関係していることです。したがって、ゼロによる除算は、静的セマンティクスの一部ではありません。これは、いくつかの動的セマンティックエラーがコンパイル時にまだ検出される場合があることを意味しています。ハードウェア制限エラーについても同様です。

しかし、すべての言語設計者または実装者は、契約またはライセンスに拘束されない限り、エラーを分類する権利があります。これは、PHPの例にも当てはまるでしょう。そして、誰もが意味的エラーと論理的エラーを区別するかもしれませんが、これらのエラーについて詳細に知らされない限り、違いを定義する方法はわかりません。1つはインテントのエラー(論理エラー)を示すために使用でき、システムでは検出できません。

プログラムには他の種類のエラーがある可能性があることに注意してください。通常、システムでは検出されません。これには特に、プログラムとその仕様の不整合(または私が意図してエラーと呼んだもの:ユーザーが意図したとおりに動作していない)、または仕様自体のエラーが含まれる可能性があります。また、実数を処理するときの丸めエラーなどのハードウェア制限によるエラーが発生する場合もあります。


-2

私の上級のコンピューティングコースノートによると、セマンティックエラーと論理エラーは、同じものの単なる異なる名前です。


1
セマンティックエラーは論理エラーとは異なります。
Juho 2014年

1
残念ながら、これは役に立ちません。あなたは他の答えに同意しませんが、あなたが提供する唯一の説明は権威への訴えです(「私の先生はそう言っています!」)。
David Richerby 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.