【问题标题】:Why doesn't this code work (Please See Details)?为什么此代码不起作用(请参阅详细信息)?
【发布时间】:2015-12-14 22:22:46
【问题描述】:

我编写了以下代码(x64 VS 2015):

typedef void(__stdcall *foo)(void* v);
HMODULE hmod = GetModuleHandle(NULL);
foo f = (foo) GetProcAddress(hmod, "_foo0");
f(0);

foo0 定义为:

extern "C" void __stdcall foo0(void* v){int a = 0;}

我已禁用所有优化和安全检查。

我想要代码做的是找到foo0的地址,然后调用它。 出于某种奇怪的原因,在GetModuleHandle() 之后调用GetLastError() 返回0x00000032,这意味着ERROR_NOT_SUPPORTED,但它确实返回了一些非零值,我认为这是可执行文件的句柄。 GetProcAddress() 返回 0x0000000000000000 和一个 GetLastError() 在它返回 0x0000007f 之后调用,这意味着 ERROR_PROC_NOT_FOUND,但我定义了 proc!

为什么会这样? GetProcAddress() 不应该与GetModuleHandle() 一起使用吗?

【问题讨论】:

  • 如果GetModuleHandle() 成功了,你为什么在GetModuleHandle() 之后阅读GetLastError()
  • Format of a C Decorated Name:“注意,在 64 位环境中,函数不会被修饰。”
  • GetLastError 仅应在您确定某事失败后使用,并且如果该“某事”被记录为以这种方式返回更多信息。在所有其他时间,它的结果都是无用的。
  • 退后一步,你想解决什么问题。我准备打赌这不是解决方案。
  • @molbdnilo:“失败” 不是调用GetLastError 的先决条件。例如,您可以在调用CreateMutex 成功后调用GetLastError

标签: c++ winapi runtime-error


【解决方案1】:

代码失败,因为GetProcAddress 要求提供的符号已从相关模块中导出。也就是说,该符号必须已列在 PE 模块的导出表中。您不导出符号,因此GetProcAddress 找不到它。因此GetProcAddress 返回NULL。如果您想使用GetProcAddress,那么您必须导出该符号。通过在 .def 文件中命名,或使用 __declspec(dllexport)

其他一些cmets:

  1. 您的调用约定似乎不匹配,stdcallcdecl
  2. 您不执行任何错误检查。对于这些特定功能,您需要检查返回值。如果这表明该函数已失败,请致电 GetLastError 以获取更多错误信息。

【讨论】:

    【解决方案2】:

    应该是:

    extern "C" __declspec(dllexport) void foo0(void* v) { int a = 0; }
    

    和:

    foo f = (foo)GetProcAddress(hmod, "foo0");
                                      ^^~~~ no need for underline
    

    至于您的 GetLastError 问题,我不确定 - 我想它可能是一些随机值。

    【讨论】:

    • OP 也在混合调用约定;你也应该指出这一点。
    • @GeekusMaximus 你的指针是stdcall,你的函数是cdecl。一旦你得到了foo0() 指针,任何调用它的尝试都会崩溃。注意调用约定。
    • 我计划在运行时注入 foo0,所以 `__declspec(dllexport)` 不起作用。
    • @GeekusMaximus:这没有意义。如果您要注入二进制映像 (DLL),__declspec(dllexport) 将起作用。如果您歪曲了您的目标,并打算编写代码是在运行时生成,那么您已经有了地址。 andlabs:在 64 位 Windows 中只有一种调用约定。由于只有一种可供选择,因此您总会选择正确的一种,即使只是巧合。
    猜你喜欢
    • 2010-10-06
    • 2019-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多