C++ 混合使用延迟dll加载和手动调用LoadLibraryA安全吗?

C++ 混合使用延迟dll加载和手动调用LoadLibraryA安全吗?,c++,windows,dll,linker,delayed-execution,C++,Windows,Dll,Linker,Delayed Execution,我正在为windows编译一个程序 我希望它检查系统中是否存在foo.dll,如果不存在,则打印错误消息并退出。这样做安全吗: 将/DELAYLOAD foo.dll标志传递给链接器 在main()的最开始处,手动调用auto handle=LoadLibraryA(“foo.dll”)并检查handle是否为NULL 如果不为空,则继续工作 在main()的末尾,调用FreeLibrary(句柄) 我想知道是否会因为延迟加载和手动调用LoadLibraryA()的混合而出现问题。另外,如果有人

我正在为windows编译一个程序

我希望它检查系统中是否存在foo.dll,如果不存在,则打印错误消息并退出。这样做安全吗:

  • /DELAYLOAD foo.dll
    标志传递给链接器
  • 在main()的最开始处,手动调用
    auto handle=LoadLibraryA(“foo.dll”)
    并检查handle是否为NULL
  • 如果不为空,则继续工作
  • 在main()的末尾,调用FreeLibrary(句柄)

  • 我想知道是否会因为延迟加载和手动调用LoadLibraryA()的混合而出现问题。另外,如果有人能建议一种更简单或更正确的方法来做我想做的事情,我将不胜感激。

    如果你要这样做,你应该在调用
    LoadLibrary()
    的“test”调用之后立即调用
    FreeLibrary()
    ——当然是在你调用其中一个例程导致自动加载之前!(当然,也就是说,假设调用成功!)这样,加载冲突就不会有问题了。(您还可以通过调用
    GetProcAddress()
    进行进一步的测试,例如检查是否存在所有必需的例程

    一旦您验证了DLL存在(而且显然是可加载的),您将继续执行—当您的可执行文件第一次调用其导出函数之一时,DLL将“自动”加载

    如果您已经(手动)加载了DLL,那么它会尝试将自己加载到同一进程中两次(我认为)。这肯定会在某个时候导致问题

    附言:这是一个很好的付账方式,IMHO!!请务必让我们知道它的价格


    编辑:在评论中进行了(有点广泛的)讨论之后,我现在很清楚,无论是在我建议的时候,还是在程序结束时(无论如何,它将被卸载),都没有必要调用
    FreeLibrary()
    。但这仍然是一个很好的解决方案!

    您应该调用FreeLibrary()在“测试”调用之后-为什么?更多的逻辑实际上根本就没有调用
    freebrary
    。如果已经(手动)加载了DLL,那么它会尝试将自己加载两次到同一进程中-这是错误的course@RbMm调用
    FreeLibrary()有什么问题
    在“测试”成功后?也许,正如Eryk所说,如果不成功,它不会加载两次,但在探测操作后“清理”不是一个好做法吗?(注意:我确实在我的帖子中写道!)@Adrian call
    FreeLibrary
    没有错(自己写的)但是,如果我们打算使用这个库-卸载它然后再次加载是为了什么?更合乎逻辑的是不卸载它already@Adrian-您搞错了。不需要再次加载。foo.dll将加载一次。在我们在main的开头加载它之后-不需要卸载/重新加载它。您混淆了加载dll和从中解析导入it@Adrian-存在两种不同的事物-load dll到内存(第一步)并从此dll解析导入函数。我最初的评论是关于-如果我们已经将foo.dll加载到内存中-没有意义卸载它并再次加载。仅此而已。但是,即使foo.dll存在,也可能是一些需要的api,它不会导出(旧版本?另一个dll)这里可能的解决方案不是简单地加载dll,而是在一开始就解决从dll的所有导入。在win 8+中,我们可以使用here api。实际上,您可以在解决延迟加载api时处理错误。如果您使用标准的
    \uuuu delayLoadHelper2
    (来自delayimp.lib),您可以实现
    \uuu pfnDliFailureHook2
    或处理
    vcpeException(ERROR\u SEVERITY\u ERROR,ERROR\u MOD\u NOT\u FOUND)
    异常。但是如果你想在找不到foo.dll的情况下停止工作-为什么不正常链接到它,而不延迟加载?你的程序只是没有启动,并显示ERROR-foo.dll NOT FOUND。如果你想在foo.dll不存在(或不导出所有api)的情况下工作,使用delayload是有意义的,但您可以以某种方式处理这种情况如果您只需要检查DLL的存在和版本信息,请调用
    LoadLibraryExW(L“foo.DLL”,NULL,LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE)
    。如果它已经映射为一个模块,它会增加引用计数并返回对它的引用。否则它会将DLL映射为一个数据节。@RbMm,延迟加载可以使程序有机会通过
    SetDefaultDllDirectories
    AddDllDirectory
    修改默认加载程序搜索路径,从而通过mitting
    PATH
    和DLL搜索中的工作目录,并通过让应用程序完全控制在何处查找其依赖项。SxS激活上下文可以实现相同的目标和更多,但它们的配置要复杂得多。@ErykSun是的,如果某些DLL很少,但不总是在正常执行中使用,也可以使用ath,我们可以只在真正需要时加载它,而不是无条件地加载。或者,如果某些api仅存在于最新版本的windows中,则可以通过延迟加载等方式处理此问题。但如果希望在一开始就停止运行应用程序,如果未找到dll-更具逻辑性的已使用,则立即导入。当然,如果不希望,请在dll不存在的情况下执行某些工作exist@RbMm也许OP想要有条件代码:一个块在DLL可以加载时执行,一个块在无法加载时运行。我相信,你的“以某种方式处理这种情况”正是OP想要建立的。