2011-06-18 10 views
5

Cで自己修正コードを移植可能にすることは可能ですか?C標準で自己修正コードが許可されていますか?

私が尋ねる理由は、(実行時に実行されるコードは実際にはvテーブルなどのデータとして生成されるため)OOPは自己変更コードに依存していますが、これがあまりにも遠すぎると、コンパイラのほとんどの最適化が妨げられるようです。例えば

:それはpを妨害しないため

void add(char *restrict p, char *restrict pAddend, int len) 
{ 
    for (int i = 0; i < len; i++) 
     p[i] += *pAddend; 
} 

最適化コンパイラは、ループの外*pAddendをホイストできました。ただし、は自己修正コードで有効な最適化ではなくなりました。

このように、Cは自己修正コードを許可していないようですが、同時に、CでOOPのようなことをすることができないということを意味しませんか? Cは本当に自己修正コードをサポートしていますか?

+2

Cには関数ポインタがあります。これは、実行時ディスパッチ機構を構築するために必要なものです。あなたは「自己修正コード」は必要ありません。 – Nemo

+0

私は、C++のOOP実装が自己修正コードを使用しているとは言いませんが、私の意見では、それは単なるデータ駆動型のコードです。バーチャルファンクションは、概念的には単純な「スイッチ」とはまったく異なります。 – Vlad

+0

@ニモ:これはまだ自己修正コードの一種ですか? – Mehrdad

答えて

7

自己修正コードがある最も重要なものは、多くの理由でCは不可能である。

  1. コンパイラによって生成されたコードは完全にコンパイラに任され、そしてどのようなようなものを見ていない可能性がありますプログラマが自分自身を変更するコードを書き込もうとすると、それは予期しています。これは、携帯性問題だけでなく、基本的なというSMCの問題です。
  2. 関数とデータポインタはCでは完全に別です。言語はそれらの間で前後に変換する方法を提供しません。この問題は、コードやデータポインタが表現を共有することを保証する実装や高水準標準(POSIX)があるため、基本的なものではありません。

それ以外は、自己変更コードは実際には本当に悪い考えです。 20年前にはいくつかの用途があったかもしれませんが、今日ではバグ、致命的なパフォーマンス、移植性の問題だけに終わりはありません。 ISAによっては、命令キャッシュがキャッシュされたコードに加えられた変更を認識するかどうかは、未定義/予測不可能な場合があることに注意してください。

最後に、vtablesは自己変更コードとは関係ありません。それは純粋に関数ポインタを変更することです。これはコードではなくデータです。

+1

+1最後の文が鍵です。なんらかの理由で私は、 'EAX'が変更されたときに' jmp EAX'のような間接的な命令が変更されると思っていました。答えをありがとう。 – Mehrdad

+1

これは当てはまりません。 POSIXとWinAPIのページ保護メカニズムを調べてください。実行時にマシンコードを生成したり、ページ保護フラグをEXECに設定したり、Cスタイルの関数ポインタを使用してコントロールに制御を渡したりすることはできません(iOSカーネルなどのコード署名を除く)。 –

3

厳密に言えば、標準を正しく理解していれば、自己修正コードをCまたはC++で移植可能な方法で実装することはできません。

uint8_t code_buffer[FUNCTION_SIZE]; 
void call_function(void) 
{ 
    ... modify code_buffer here to the machine code we'd like to run. 
    ((void (*)(void))code_buffer)(); 
} 

これは法的なものではなく、最も近代的なアーキテクチャでクラッシュします:

C/C++での自己書き換えコードは次のようなものを意味します。これは、ハーバード・アーキテクチャー上で実装することは不可能です。実行可能コードは厳密には読み取り専用であるため、どの標準にも組み込むことはできません。

最新のOSには、このハッカーを実行できる機能があります。この機能は、動的再コンパイラによって使用されます。たとえばUnixではmprotect()です。

+1

そして、*自己修正コードは、 "新鮮な"コードを書いて実行するもう1つのコードです。 Mehrdadが観察しているように、機械命令が必ずしもASTとの明確な関係を必ずしも持っているわけではないので、最初にそのコードがどのように生成/最適化されたか分からなければ、コンパイラ生成コードを修正することは非常に困難です。 –

+0

"自己修正C"を書くことはできませんが、Cコンパイラが "自己修正マシンコード"を発行することは確かに可能です。私は質問が両方のことを許すと思います。OPがどちらも気にしていないかどうか、Cコンパイラがこれを実行したかどうかわかりません。 – hippietrail

関連する問題