5

存在しない、または間違ったアリティを持つ別のモジュールで関数を呼び出したときに、コンパイル時のエラーや警告が表示されないのはなぜですか?

コンパイラーは、これを可能にするために、モジュール内のすべてのエクスポート情報を持っています。それはまだ実装されていないだけですか、それとも私が見ないことが不可能であるという技術的な理由がありますか?

4

6 に答える 6

6

なぜそれが欠落しているのかわかりません(おそらく、モジュールが完全に分離されており、一方のコンパイルが他方に実際に依存していないためですが、それは単なる推測です)。しかし、ダイアライザーの静的分析では、このような問題を見つけることができると思います。http://www.erlang.org/doc/man/dialyzer.htmlをご覧ください

これはシステム自体の一部なので、ワークフローに含めてみてください。

于 2013-03-13T22:53:07.500 に答える
4

他の人が言っているようです。モジュールは個別にコンパイルされ、コンパイル時に存在する環境が実行時に終了する環境と同じであるという保証はまったくありません。これは、コンパイル時にモジュールまたはその中の関数の存在についてチェックを行うことは基本的に無意味であることを意味します。実行時に、そのモジュールがロードされる場合とされない場合があります。呼び出す関数がモジュールで定義されている場合とされていない場合があります。または、予期したものとはまったく異なる動作をする場合があります。

これはすべて、Erlangシステムの非常に動的な性質によるものです。実行時にシステムに何があるかを定義する実際の方法はありません。ホットコードの読み込みはこの一部であり、システムの動的な性質により適切に機能します。つまり、実行時にシステムを再定義、異なるインターフェイスを使用して既存のモジュールの新しいバージョンをロードし、完全に新しいモジュールをロードして既存のモジュールを削除することができます。

これが機能するためには、モジュールまたは関数の存在に関するすべてのチェックを実行時に実行する必要があります。

ダイアライザーのようなツールはこれを助けることができますが、実行時に「面白い」ことは何もしないことを前提としており、チェックするシステムは実行するシステムと同じです。もちろんこれはすべて良いですが、非常に静的です。そして、すべてにおいて、動的であるというErlangの性質に反します。

残念ながら、この場合、ケーキを持って食べることはできません。

于 2013-03-14T21:29:21.153 に答える
2

このxrefアプリケーションを使用して、非推奨、未定義、および未使用の関数(およびその他)の使用状況を確認できます。

モジュールをコンパイルしますdebug_info

Eshell V6.2  (abort with ^G)
1> c(test, debug_info).
{ok,test}

モジュールを確認してくださいxref:m/1

2> xref:m(test).
[{deprecated,[]},
 {undefined,[{{test,start,0},{erlang,foo,0}}]},
 {unused,[]}]

あなたはここでもっとチェックしたいかもしれませんxref

Erlang-外部参照-相互参照ツール(ツールユーザーガイド)

Erlang --xref(ツールリファレンスマニュアル)

于 2014-11-20T11:38:32.527 に答える
1

私の意見では、すべてではないにしても、ほとんどの場合、コンパイラはコンパイル時に関数が存在することを確認しません。一般的に必要なのは、関数のプロトタイプ宣言です。戻り値の型、すべての引数のリストと型です。これは、C / C ++で、各モジュール定義にsome_file.hを含めることによって行われます(.cまたは.cppではありません)。

Erlangでは、このタイプの検証はプログラムの実行中に動的に行われるため、これらの定義を含める必要はありません。Erlangでは実行中のアプリケーションをアップグレードできるため、アプリケーションの存続期間中に関数の型が変更されたり、意図的または誤って関数が消えたりする可能性があるため、まったく役に立ちません。これが、Erlangデザイナーがビルド時ではなく実行時にこの検証を行うことを選択した理由です。

あなたが話すエラーは、一般に、コード生成のリンクフェーズで発生します。このフェーズでは、「コンパイラ」がオブジェクトコードの個々の部分をすべて集めて実行可能ファイルまたはライブラリを構築しようとします。このフェーズでは、リンカがすべての外部を解決します。アドレス(共有変数、静的呼び出しの場合...)。このフェーズはアーランには存在しません。モジュールは完全に自己完結型です。アプリケーションの他の部分とは何も共有せず、変数や関数のアドレスも共有しません。

もちろん、実行中の本番プログラムを更新する前に、いくつかのツールを使用してテストを行う必要がありますが、これらの検証は、アルゴリズム自体の正確さとまったく同じレベルの重要性を持っていると思います。

于 2013-03-14T05:14:55.130 に答える
1

ホットコードの読み込みが原因です。各モジュールは、特定の時間にロードできます。したがって、A関数を呼び出すモジュールコードがある場合、モジュールのソースコードに関数がないB:F場合、コンパイル時にそれが間違っているとは言えません。これを想像してみてください。を呼び出してモジュールをコンパイルします。関数なしでモジュールをメモリにロードします。次に、呼び出しを含むが呼び出しないモジュールをロードします。次に、モジュールの新しいバージョンを。でコンパイルします。次に、この新しいモジュールをロードすると、呼び出すことができ、すべてが完全に正しくなります。モジュールがモジュールをオンザフライで作成し、ロードするとします。そのモジュールが間違っていることを特定の時間に伝えることはできませんBB:FAB:FBB:FAB:FBB:FB:FABA存在しない関数への呼び出しが含まれていますB:F

于 2013-03-13T23:38:27.910 に答える
1

alphaを呼び出すモジュールなどをコンパイルするbeta:some_function(...)と、コンパイラは実行時にの特定のバージョンが使用されていると想定できませんbetabetaたぶん、コンパイルした後に新しいバージョンをコンパイルするalphaと、これは正しくsome_functionエクスポートされます。alphaたぶん、他のすべてのモジュールがある別のホストで使用するためにアップロードします。

したがって、コンパイラはリモート呼び出しをコンパイルするだけで、エラー(存在しないモジュールまたは関数)は実行時に解決され、のバージョンbeta ロードされます。

于 2013-03-14T08:37:23.020 に答える