在(Visual)C++中调用动态创建函数的约定

Las*_*olt 5 c c++ x86 visual-c++

我使用以下类型在运行时创建一个新函数:

typedef int (*pfunc)(int);

union funcptr {
  pfunc x;
  byte* y;
};
Run Code Online (Sandbox Code Playgroud)

这使我能够编写指令y,然后调用这个函数:

byte* p = (byte*)VirtualAllocEx(GetCurrentProcess(), 0, 1<<16, MEM_COMMIT, PAGE_EXECUTE_READWRITE );

// Write some instructions to p

funcptr func;
func.y = p;

int ret = func.x(arg1); // Call the generated function
Run Code Online (Sandbox Code Playgroud)

了解C++如何准备参数(调用约定)至关重要,因此我查找了项目属性(Visual C++),我可以看到它的用途__cdecl.它应该根据以下内容在堆栈上放置参数:http://msdn.microsoft.com/en-us/library/aa271989(v = vs.60).aspxhttp://en.wikipedia.org/wiki/X86_calling_conventions #cdecl但是当我查看生成的程序集时,参数将被移动到EAX寄存器.

我想绝对肯定这些论据是如何准备的.所以我忽略了一些关于cdeclVisual C++优化调用的内容,如果是这样,我如何确保它不会发生?

最诚挚的问候,Lasse Espeholt

Dav*_*nan 5

EAX寄存器用于函数的返回值.您在评论中说明您正在编译使用/Gd,因此该函数将使用__cdecl.同样,在我看来,pfunc用一个显式标记你的函数类型的声明是有意义的,__cdecl这样就不会有混淆和不匹配的空间.

当然,没有什么可以阻止你使用编译器支持的其他调用约定之一.最重要的一点是,无论您采用何种调用约定,都应该明确指定函数指针的调用约定,因为编译器只负责接口的一半.

  • @lasseespeholt,无论如何都要尝试`__cdecl`(例如`typedef int(__ cdecl*pfunc)(int);`)并告诉我们发生了什么. (3认同)