c++ - 如果 DLL 移动到不同的位置,Windows DLL 函数的行为会有所不同

标签 c++ c windows dll

我正在尝试在 CI 机器上的 Unreal 中调试 DLL 的一些非常不透明的问题(有关更多信息,请参阅 Unreal: Diagnosing why Windows cannot load a DLL)。 glu32.dll 似乎是 Unreal 进程崩溃的 DLL,并且由于 Windows Server 不包含普通 Windows 10 所包含的所有与图形相关的 DLL,因此建议我上传某些 DLL从我的机器/Microsoft 可再发行组件中,以确保虚幻构建过程可以运行。

出于理智的目的,我编写了一个小实用程序来测试我的计算机上的 glu32.dll 是否可以动态加载并可以正确调用其函数。我计划很快在麻烦的 CI 机器上运行这个可执行文件,看看会发生什么。

程序代码如下:

#include <windows.h> 
#include <iostream>
#include <GL/gl.h>

extern "C"
{
    typedef const GLubyte* (__stdcall *ErrorStringFunc)(GLenum error);
}

int main(int argc, char** argv)
{
    if (argc < 2)
    {
        std::cerr << "Usage: GLU32Loader.exe <path to glu32.dll>" << std::endl;
        return 1;
    }

    const char* path = argv[1];
    std::cout << "Attempting to load: " << path << std::endl;

    HMODULE dllHandle = LoadLibraryA(path);

    if (!dllHandle)
    {
        std::cerr << "Could not load " << path << std::endl;
        return 1;
    }

    std::cout << "Successfully loaded DLL: 0x" << dllHandle << std::endl;

    const char* funcName = "gluErrorString";

    std::cout << "Looking up function: " << funcName << std::endl;
    ErrorStringFunc func = reinterpret_cast<ErrorStringFunc>(GetProcAddress(dllHandle, funcName));

    if (func)
    {
        std::cout << "Successfully loaded function: 0x" << func << std::endl;

        const GLubyte* str = (*func)(100902);
        std::cout << "Error string for value 100902: \"" << str << "\" (0x" << static_cast<const void*>(str) << ")" << std::endl;
    }
    else
    {
        std::cerr << "Failed to load function " << funcName << std::endl;
    }

    FreeLibrary(dllHandle);

    return 0;
}

当我运行可执行文件并将其指向 System32 文件夹中的 glu32.dll 时,我得到了预期的输出:

> GLU32Loader.exe "C:\Windows\System32\glu32.dll"
Attempting to load: C:\Windows\System32\glu32.dll
Successfully loaded DLL: 0x00007FFC7A350000
Looking up function: gluErrorString
Successfully loaded function: 0x00007FFC7A35C650
Error string for value 100902: "out of memory" (0x000001E5757F51D0)

但是,如果我将 DLL 复制到桌面并再次运行该程序,虽然 DLL 和函数看起来已加载,但从函数返回的字符串为空:

> GLU32Loader.exe "C:\Users\Jonathan\Desktop\glu32.dll"
Attempting to load: C:\Users\Jonathan\Desktop\glu32.dll
Successfully loaded DLL: 0x00007FFC8DDB0000
Looking up function: gluErrorString
Successfully loaded function: 0x00007FFC8DDBC650
Error string for value 100902: "" (0x0000025C5236E520)

为什么会这样呢?它是完全相同的 DLL,只是位于不同的文件夹中,而且我本以为它引用的任何其他依赖 DLL 应该仍然可用,因为它们都在 System32 中。是否有我不熟悉的 Windows DLL 的某些神秘属性可能会导致这种情况发生?

最佳答案

这是一个说明为什么不应乱用系统 DLL 的示例。

与许多 Microsoft DLL 一样,有问题的 DLL 使用 MUI (多语言用户界面)。

如果查看它的资源,除了MUI类型的资源之外,它没有任何资源,指向包含相应.mui的文件夹。文件,其中包含其实际(国际化)资源。

所以,如果你还想复制的话,至少也复制对应的.mui文件:

  • System32\glu32.dll<my_files>\glu32.dll
  • System32\en-US\glu32.dll.mui<my_files>\en-US\glu32.dll.mui

en-US根据默认区域设置,部分内容在您的系统上可能会有所不同。

关于c++ - 如果 DLL 移动到不同的位置,Windows DLL 函数的行为会有所不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68389730/

相关文章:

c++ - Visual Studio 在命令行中定义预处理器指令

c - c中字符串数组的内存泄漏

windows - 使用 xperf 获取符号

c++ - 如何防止将整数分配给 char 字符串?

c++ - QWebEnginePage 打印为 PDF 不会像 Google Chrome 那样打印 PDF 中的可选文本

c - 在字符串 C 中搜索字符串的函数

c - 在C中访问字符串数组的第一个元素

r - mc.cores > 1 在 Windows 上不受支持

ruby-on-rails - Windows 上的 Ruby 导致错误 Cannot load such file bcrypt_ext

c++ - 如何将一个结构体的地址分配给另一个结构体?