0

Windows x86 または WOW64 で動作する以下のコード スニペットをコンパイルして実行しようとしていますが、Windows x64 ではエラー アクセス違反でクラッシュします。

gcc と Microsoft C/C++ コンパイラの両方でコンパイルします。

/*Microsoft (R) C/C++ Optimizing Compiler Version 15.00.30729.01 for x64
 (x64)cl -W3 -Zi tx.c -Fetx64
 (x86)cl -W3 -Zi tx.c -Fetx32

 gcc (tdm64-1) 4.7.1
 (x64)gcc -m64 -Wall -O2 -o tx64 tx.c
 (x86)gcc -m32 -Wall -O2 -o tx32 tx.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int (*fpPUTS)( const char *str ); /*function pointer that takes an const char * as an argument and returns int*/                                          
typedef void (*fpMEMEXEC)( fpPUTS pPuts, char *str ) ;/*function pointer on which first argument is pointer to above function*/

void toMem( fpPUTS pPuts, char *str )
{
    pPuts( str );
}   

int main(int argc, char* argv[])
{
    fpMEMEXEC   pMemexec;
    pMemexec = (fpMEMEXEC) malloc(4*1024);/* Allocate 4 KB memory space to the function pointer */
    memcpy( pMemexec, toMem, 4*1024);    /*  Copy the content of toMem into newly allocated memory */
    pMemexec( puts, "Hello word !!\n"); /* execute it in memory */
    return 0;
}

私の質問は、このコードが 64 ビット環境で正しく動作しないのはなぜですか?
このコードを適切に機能させるためには、どのようなルールが満たされていない必要がありますか?

4

1 に答える 1

3

お使いのシステムには、おそらくDEP (データ実行防止) が備わっています。これは、すべてのページが書き込み可能または実行可能のいずれかであり、両方ではないことを意味します。

32 ビット システムでは、現在のプロセスに対して SetProcessDEPPolicy を無効にするためにSetProcessDEPPolicyを使用する必要があります。

64 ビット システムでは、PAGE_EXECUTE_READWRITEを使用して割り当てる必要があります。

pMemexec = VirtualAlloc(0, 4*1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

おそらく、これこの質問、およびこの例を見たいと思うでしょう。


ご指摘の通り、動作を保証するものではありません

  1. 私が知る限り、C プログラミング言語は、そのようなコピーが適切に呼び出し可能な関数を作成することを保証しません。
  2. 関数がページ アラインされておらず (可能性が高い)、次のページが割り当てられていない場合は、割り当てられていないメモリから読み取ろうとしていることに気付くでしょう。したがって、どういうわけか、関数の長さを正確に見つける必要があります。
于 2013-06-30T15:04:41.410 に答える