7

ここでは C を扱います。foo関数が保存されているメモリ内のポイントにアクセスできるかどうか、たとえば、関数の内容をメモリ内の別のポイントにコピーできるかどうか疑問に思っています。具体的には、次のことを機能させようとしています。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void foo(){
    printf("Hello World");
}

int main(){

    void (*bar)(void) = malloc(sizeof foo);
    memcpy(&bar, &foo, sizeof foo);


    bar();
    return 0;
}

しかし、それを実行するとバスエラーが発生します: Bus error: 10. foofunction の内容をメモリのスペースにコピーしてからbar、新しく作成した function を実行しようとしていますbar

これは、そのようなことが可能かどうかを確認し、C 言語の複雑さを明らかにする以外の理由はありません。これがどのような実用的な用途があるかは考えていません。

これを機能させるためのガイダンスを探しています。または、これが機能しない理由を説明してください。

編集いくつかの回答を見て、 readwrite、および実行可能メモリについて学習したところ、実行可能メモリに書き込むことで C でその場で関数を作成できることがわかりました。

4

2 に答える 2

8

標準 C では、実行しようとしているのは実装定義の動作であり、移植可能には機能しません。特定のプラットフォームでは、これを機能させることができる場合があります。

通常、メモリmallocは実行可能ではありません。そこにジャンプすると、バスエラー ( SIGBUS) が発生します。POSIX ライクなシステムを使用していると仮定するとmmap、メモリ領域を実行可能にする および フラグを使用して関数にメモリを割り当てるかmprotect、領域を実行可能としてマークするために使用します。

また、提供するメモリの量にも注意する必要があります。単純に関数のサイズを取得して、それが関数の長さであると期待することsizeofはできません。この種の機能を提供するように設計されていません。他のアプローチを使用して関数の長さを調べる必要があります。

于 2015-11-27T20:18:57.873 に答える
6

最新のデスクトップでは、仮想メモリ マネージャーが邪魔になります。メモリ領域には、 readwriteexecuteの 3 種類のアクセスがあります。コード セグメントに実行権限しかないシステムではmemcpy、 はバス エラーで失敗します。コード セグメントのみが実行権限を持つ、より一般的なケースでは、関数をコピーすることはできますが、実行barすることはできません。

また、関数のサイズを決定することも問題です。次のプログラムを検討してください

void foo( int *x )
{
    printf( "x:(%zu %zu) ", sizeof x, sizeof *x );
}

int main( void )
{
    int x = 0;
    foo( &x );
    printf( "foo:(%zu %zu)\n", sizeof foo, sizeof *foo );
}

私のシステムでは、出力は、関数ポインターまたは関数自体を取得する操作がサポートされていないことx:(8 4) foo:(1 1)を示しています。sizeof

于 2015-11-27T20:19:59.660 に答える