コンピュータにおいて、エイリアシングとは、メモリ内のデータ位置がプログラム内で異なるシンボル名でアクセスできる状況を指します。そのため、あるシンボル名でデータを変更すると、暗黙的にすべてのエイリアス名に関連付けられた値も変更されてしまい、プログラマが意図しない結果となる場合があります。結果として、エイリアシングはプログラムの理解、分析、最適化を著しく困難にします。エイリアシングアナライザは、プログラムにおけるエイリアシングを理解するための有用な情報を作成・計算することを目的としています。
エイリアシングは、メモリ内の1つの場所を複数の名前で参照できる言語(例えば、ポインタを使用する場合)で発生する可能性があります。これは、ポインタ引数を受け取る関数でよく見られる問題であり、特に渡されたメモリ領域に対して複雑な操作を行う関数については、エイリアシングに対する許容度(または許容度の欠如)を注意深く文書化する必要があります。
場合によっては、制御されたエイリアシング動作が望ましいことがあります(つまり、C のメモリレイアウトによって可能になるエイリアシング動作とは異なり、エイリアシング動作が指定されているということです)。これはFortranでは一般的な慣習です。Perlプログラミング言語では、ループなどの一部の構造でエイリアシング動作が指定されています。これにより、 特定のデータ構造を少ないコードで直接変更できます。たとえば、foreach
my @array = ( 1 , 2 , 3 );foreach my $element ( @array ) { # $element をインクリメントすることで、 # $ element が@array の各要素に順番に「エイリアス」されているため、 # @array を自動的に変更します。 $element ++ ; }print "@array \n" ;結果として「2 3 4」が出力されます。エイリアシング効果を回避したい場合は、インデックス変数の内容を別の変数にコピーして、コピーした変数を変更すればよいでしょう。
エイリアシングが可能な場合、オプティマイザは変数について保守的な仮定を置く必要があることがよくあります。たとえば、変数の値 (例えば が 5 である) がわかっていると、通常は特定の最適化 (定数伝播xなど) が可能になります。ただし、コンパイラは、別の変数への代入後 (たとえば、C では) にこの情報を使用することはできません。なぜなら、 が のエイリアスである可能性があるからです。これは、 のような代入後に発生する可能性があります。 へのこの代入の結果として、 の値も変更されるため、 が 5 であるという情報を後続のステートメントに伝播すると、潜在的に誤りになります (が実際に のエイリアスである場合)。ただし、ポインタに関する情報がある場合、定数伝播プロセスは、が のエイリアスである可能性があるか、といったクエリを作成できます。そして、答えが no であれば、 を安全に伝播できます。*y = 10*yxy = &x*yxx*y = 10*yxx*yx = 5
エイリアシングによって影響を受けるもう1つの最適化は、コードの並べ替えです。コンパイラがxが とエイリアシングされていないと判断した場合*y、 の値を使用または変更するコードは、スケジューリングの改善やループ最適化の促進につながる場合、xの代入の前に移動できます。*y = 10
このような最適化を予測可能な方法で実現するために、C プログラミング言語のISO 標準(新しいC99版を含む、セクション 6.5、第 7 項を参照) では、異なる型のポインタを使用して同じメモリ位置にアクセスすることは (いくつかの例外を除いて) 違法であると規定しています。したがって、コンパイラは、そのようなポインタがエイリアスしないものと想定することができます。このルールは厳密エイリアシング規則として知られており、パフォーマンスが大幅に向上することがありますが[ 1 ]、そうでなければ有効なコードが壊れることがあります。いくつかのソフトウェア プロジェクトは、C99 標準のこの部分を意図的に違反しています。たとえば、Python 2.x は参照カウントを実装するためにこれを行い[ 2 ]、この最適化を有効にするために Python 3 の基本オブジェクト構造に変更を加える必要がありました。Linuxカーネルは、厳密エイリアシングがインライン コードの最適化に問題を引き起こすため、これを行っています[ 3 ] 。このような場合、 gccでコンパイルすると、予期しないコードを生成する可能性のある不要な最適化を防ぐために、オプションが呼び出されます。-fno-strict-aliasing
エイリアシングという用語は、ハードウェア設計の選択またはハードウェア障害により、使用可能なアドレス ビットの 1 つ以上がメモリ選択プロセスで使用されない状況を説明するためにも使用されます。[ 4 ]これは、インストールされているメモリ デバイスをサポートするために必要なアドレス ビットよりも多くのアドレス ビットが使用可能な場合の設計上の決定である可能性があります。障害が発生すると、1 つ以上のアドレス ビットが短絡したり、グランド(論理 0) または電源電圧 (論理 1) に強制的に接続されたりする可能性があります。
この例では、8 つのロケーションを持つメモリ設計を想定し、アドレス線は 3 本(またはビット、 2³ = 8なので)のみを必要とします。アドレスビット(A2 から A0 と命名)は、標準的なバイナリカウンタ方式で、次のようにデコードされ、一意のメモリロケーションが選択されます。
上記の表では、アドレスビットの8つの固有の組み合わせそれぞれが異なるメモリ位置を選択します。しかし、1つのアドレスビット(例えばA2)がグランドに短絡された場合、表は次のように変更されます。
この場合、A2が常にゼロであるため、最初の4つのメモリ位置が複製され、次の4つのメモリ位置として再び現れます。メモリ位置4から7はアクセスできなくなります。
この変更が別のアドレスビットで発生した場合、復号結果は異なるが、一般的には影響は同じである。つまり、1つのアドレスビットが失われると、利用可能なメモリ空間が半分になり、残りの空間で重複(エイリアシング)が発生する。