【问题标题】:FreeLibrary Failing免费图书馆失败
【发布时间】:2020-05-10 19:55:59
【问题描述】:

我第一次尝试编写 DLL,并且有一个我正在尝试处理的项目。我编写我的 DLL,这是我能想到的最简单的 DLL,然后编译它。我转到我的可执行文件,调用 LoadLibrary,它加载它就好了,我可以像往常一样从 DLL 调用函数。然而,FreeLibrary 每次都返回 1。我还没有能够成功卸载 DLL(我正在玩热重载 DLL,这是我为了练习而拼凑起来的解决方案)。

这是我的代码:

可执行程序的program.cpp:

#include <iostream>
#include <windows.h>

typedef void (*_TestFunction)();

int main()
{
    HMODULE hinstDLL = LoadLibrary(L"Test.dll");

    _TestFunction TestFunction = (_TestFunction)GetProcAddress(hinstDLL, "TestFunction");

    TestFunction();

    BOOL result = FreeLibrary(hinstDLL);
    std::cout << result << std::endl;

    if (hinstDLL != NULL)
    {
        std::cout << "Still loaded" << std::endl;
    }

    std::cin.ignore();
    return 0;
}

我的 DLL 的 dllmain.cpp:

#include "pch.h"

#define DLL_EXPORT

#include "dllmain.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        std::cout << "DLL Load Process" << std::endl;
        break;
    case DLL_THREAD_ATTACH:
        std::cout << "DLL Load Threaded Process" << std::endl;
        break;
    case DLL_THREAD_DETACH:
        std::cout << "DLL Unload Threaded Process" << std::endl;
        break;
    case DLL_PROCESS_DETACH:
        std::cout << "DLL Unload Process" << std::endl;
        break;
    }
    return TRUE;
}

DLL_FUNCTION void TestFunction()
{
    std::cout << "Hello World" << std::endl;
}

dllmain.h:

#pragma once

#ifdef DLL_EXPORT
#define DLL_FUNCTION extern "C" __declspec(dllexport)
#else
#define DLL_FUNCTION extern "C" __declspec(dllimport)
#endif

我的预编译头文件只包含用于记录信息的 DLL 和 TestFunction() 的 iostream。

我不知道为什么它不起作用,而且我已经被这个问题困扰了将近一整天。任何帮助表示赞赏。

【问题讨论】:

  • “然而,FreeLibrary 每次都返回 1。” - 当FreeLibrary 返回非零时,表示函数成功。是什么让您认为它失败了?
  • 您应该阅读this(尤其是第二个答案)关于在DllMain 中使用cout
  • 请参阅this link,了解 DllMain 中的更详细限制列表。
  • @AdrianMole:您对“第二个答案”的描述不明确。你按什么排序答案?投票?最老的答案?活动?
  • @AndreasWenzel 对不起 - MSalters 提供的答案,here

标签: c++ dll


【解决方案1】:

根据Microsoft Documentation,如果成功,FreeLibrary 将返回非零值。我刚刚在最简单的例子中验证了它:

#include <iostream>
#include <Windows.h>

int main()
{
    const HMODULE handle = LoadLibraryW(L"kernel32.dll");

    std::cout << FreeLibrary(handle);

    return 0;
}

按预期打印 1

如果在您调用 FreeLibrary 时它使用 DLL_PROCESS_DETACH 调用 DllMain,那么一切都很好,您的 DLL 将从内存中完全卸载。

【讨论】:

  • 好的。我关于退出代码的错误。但是,后续问题,我现在调用 FreeLibrary 两次以检查它是否正常工作,虽然 FreeLibrary 成功,但它没有从内存中卸载 DLL,即它没有调用 DLL_PROCESS_DETATCH 中的任何内容。有没有办法强制它卸载?
  • @SloanPhillippi 你确定没有调用 DLL PROCESS DETACH 吗?我刚刚用你的例子在我的电脑上检查了它,它对我有用,我得到了输出 DLL Load Process 然后 DLL Unload Process
  • 对我来说,虽然它确实在程序退出时调用它,但在打印“仍然加载”之前它不会调用它,这意味着 FreeLibrary() 没有触发它。只是退出的程序为我触发了它。您是否设法在“仍在加载”出现之前打印它?如果是这样,也许我在某个地方犯了一个非常愚蠢的错误。
  • @SloanPhillippi 我刚刚注意到这个“仍在加载”的时刻。为什么你希望这个指针在那里变成 NULL?它不会 - 它将包含可能无效的地址。 FreeLibrary 无法更改此指针,至少因为您通过副本将其传递到那里。
  • 我知道它不会改变。我从对我原始帖子的评论中了解到这一点。不过,DLL_PROCESS_DETACH 中的代码应该在此之前调用,因为 FreeLibrary() 是在此之前完成的,对吧?我知道仍然加载并不意味着它仍然加载,但是 PROCESS_DETACH 没有被调用的事实表明它仍然在那里,对吗?即使调用了 FreeLibrary,如果我在调用 FreeLibrary() 之后但在程序退出之前尝试修改 DLL,它会说它无法打开它进行写入,因为可执行文件正在保留它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-04
  • 1970-01-01
  • 1970-01-01
  • 2021-10-04
  • 2011-08-15
  • 1970-01-01
  • 2019-11-03
相关资源
最近更新 更多