LoadLibrary返回NULL,GetLastError返回998

在使用LoadLibrary装载某个dll的时候返回NULL,然后调用GetLastError返回998,意思是说“内存位置访问无效。”,问题很奇怪,因为前一段时间还能正确加载,网上搜索也是说什么的都有,最后调查发现是由于LoadLibrary是在应用程序全局变量初始化的时候调用的,如果LoadLibrary放到应用程序初始化完成后就不会出现这个问题(或者在主窗体构造时),看样子这个动态库不能装载过早,可能是由于其他系统依赖库还没有加载造成的(比如LoadLibrary函数所在的库)。


2017年9月5号最新进展(备注:c++builder的exe调用VC++ dll):

LoadLibrary中的参数使用变量时,不会出现此问题,或者使用LoadLibraryA和LoadLibraryW也不会出现此问题,比如:

String dllName = "decoder.dll";

hDll = LoadLibrary(dllName.c_str());//ok

hDll = LoadLibraryA("decoder.dll");//ok

hDll = LoadLibraryW(L"decoder.dll");//ok

//hDll = LoadLibrary(_T("decoder.dll"));//fail

最后定位到一个其他函数中的一个数组初始化会影响到LoadLibrary函数返回值,

char szHead[5] = {0};

C++ builder 太奇怪了,或者还没有找到真正的原因!

<think>好的,用户想了解Windows API中LoadLibrary函数的用法。首先,我需要回忆LoadLibrary的基本功能和用途。LoadLibrary主要用于动态加载DLL文件到进程的地址空间,这对于动态链接和运行时模块加载非常重要。接下来,我需要确定用户可能关心的方面,比如函数原型、参数、返回值、使用示例以及注意事项。 根据提供的引用内容,特别是引用[2]中提到了使用LoadLibrary进行DLL注入的步骤。这提示我应该包括如何在实际编程中使用该函数,比如在远程线程注入中的具体应用。同时,引用[1]提到拦截LoadLibrary的情况,可能需要注意安全性或钩子的问题,但用户的问题主要集中在用法上,这部分可能作为高级主题提及。 用户可能也需要了解不同版本的LoadLibrary,比如A和W版本的区别,对应ANSI和Unicode字符集。此外,错误处理也是关键,比如如何处理加载失败的情况,检查返回的HMODULE是否为NULL,并通过GetLastError获取错误代码。 还需要考虑使用后的资源释放,即使用FreeLibrary函数来减少DLL的引用计数。引用[2]中提到的远程线程注入示例中的注意事项,比如等待线程执行完毕再释放内存,这也是一个重要的点,防止崩溃。 另外,用户可能对实际代码示例感兴趣,特别是如何在C/C++中调用LoadLibrary,以及如何处理路径和名称。引用[4]提到了通过JNA在Java中调用VHD API,虽然不直接相关,但可能用户对跨语言调用也有兴趣,但当前问题应专注于Windows API的原生使用。 最后,生成相关问题时,需要覆盖函数的基本用法、错误处理、不同字符集版本、动态加载的应用场景,以及安全注意事项,比如DLL劫持问题。确保问题能够引导用户进一步深入学习和理解LoadLibrary的各个方面。</think>### LoadLibrary函数用法解析 在Windows API中,`LoadLibrary`函数用于将动态链接库(DLL)加载到调用进程的地址空间中。其核心功能是**动态加载模块**,常用于运行时按需加载代码或资源。 --- #### 一、函数原型与参数 ```c HMODULE LoadLibraryA(LPCSTR lpFileName); // ANSI版本 HMODULE LoadLibraryW(LPCWSTR lpFileName); // Unicode版本 ``` - **参数**: - `lpFileName`:DLL文件的路径或名称(支持相对路径) - **返回值**: - 成功:返回模块句柄(HMODULE) - 失败:返回`NULL`,可通过`GetLastError()`获取错误码 > 实际开发中通常使用宏`LoadLibrary`,编译器根据字符集自动选择A/W版本[^2]。 --- #### 二、典型使用场景 1. **动态功能扩展** 如插件系统,运行时加载特定功能的DLL。 2. **资源按需加载** 减少程序启动时的内存占用。 3. **DLL注入技术** 通过远程线程调用`LoadLibrary`实现跨进程模块加载(需配合`CreateRemoteThread`)[^2]。 --- #### 三、代码示例(C/C++) ```c #include <windows.h> int main() { // 加载user32.dll(显式链接) HMODULE hModule = LoadLibrary(TEXT("user32.dll")); if (hModule == NULL) { DWORD err = GetLastError(); printf("加载失败,错误码:%d\n", err); return 1; } // 获取函数指针 FARPROC pFunc = GetProcAddress(hModule, "MessageBoxW"); // 使用函数... // 卸载DLL FreeLibrary(hModule); return 0; } ``` --- #### 四、关键注意事项 1. **搜索路径顺序** Windows按以下顺序查找DLL: - 应用程序目录 - 系统目录(如`System32`) - 当前工作目录 - PATH环境变量目录 2. **引用计数管理** 每次调用`LoadLibrary`会增加引用计数,需通过`FreeLibrary`释放。 3. **DLL劫持风险** 避免使用非限定路径,防止恶意DLL被优先加载[^1]。 --- #### 五、错误处理建议 ```c HMODULE hDll = LoadLibrary(L"mydll.dll"); if (hDll == NULL) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); MessageBox(NULL, (LPCTSTR)lpMsgBuf, L"错误", MB_OK); LocalFree(lpMsgBuf); } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值