You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法调用DLL函数:HelloWorld函数定位失败排查求助

问题

尝试调用一个仅用于显示MessageBox的DLL,但加载器无法定位其中的HelloWorld函数,程序运行后无任何反应。此前测试user32.dll的SwapMouseButton函数可正常调用。已定义导入导出,但怀疑存在错误,也不确定调用约定是否正确。相关代码如下:

原导入导出定义

#ifndef INDLL_H
#define INDLL_H

#ifdef EXPORTING_DLL
extern __declspec(dllexport) void HelloWorld();
#else
extern __declspec(dllimport) void HelloWorld();
#endif

#endif 

原Hello World DLL代码

/* Hello World DLL */
#include "stdafx.h"
#define EXPORTING_DLL
#include "sampleDLL.h"
#include "pch.h"

BOOL APIENTRY DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    return TRUE;
}

void HelloWorld()
{
    MessageBox(NULL, TEXT("Hello World"),
        TEXT("In a DLL"), MB_OK);
}  

原DLL加载器代码

/* DLL Loader */
#include <windows.h>
#include <iostream>

typedef int(__stdcall* f_funci)();

int main()
{
    HINSTANCE hGetProcIDDLL = LoadLibrary("PATH\\LoadME.dll");

    if (!hGetProcIDDLL) {
        return EXIT_FAILURE;
    }

    // resolve function
    f_funci functon = (f_funci)GetProcAddress(hGetProcIDDLL, "HelloWorld");
    if (!functon) {
        std::cout << "Function Could Not Be Located" << std::endl;
        return EXIT_FAILURE;
    }

    std::cout << "returned " << functon() << std::endl;

    return EXIT_SUCCESS;
} 
问题分析与修复

1. C++名字修饰导致函数名无法匹配

默认情况下,C编译器会对函数名进行修饰(添加参数类型、调用约定相关后缀),使得GetProcAddress无法通过原始的"HelloWorld"字符串找到函数。必须用extern "C"包裹导出函数,禁用C名字修饰。

2. 调用约定不匹配

DLL中的HelloWorld默认使用__cdecl调用约定,但加载器中定义的函数指针是__stdcall,这会导致调用栈失衡,引发崩溃或未定义行为。需要统一两者的调用约定。

3. 返回值类型不匹配

DLL中的HelloWorld是void类型,但加载器中函数指针定义为返回int,会导致调用后读取无效返回值,引发未定义行为。

4. 其他细节问题

  • DLL代码中未显式包含windows.h,虽然可能通过预编译头间接包含,但显式包含更稳妥;
  • 加载器中未调用FreeLibrary释放DLL资源,可能导致资源泄漏;
  • 建议使用宽字符版本的LoadLibraryW避免路径编码问题。
修正后的代码

修正后的导入导出头文件

#ifndef INDLL_H
#define INDLL_H

#ifdef __cplusplus
extern "C" {
#endif

#ifdef EXPORTING_DLL
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

// 统一指定__stdcall调用约定
DLL_API void __stdcall HelloWorld();

#ifdef __cplusplus
}
#endif

#endif 

修正后的DLL代码

/* Hello World DLL */
#include "stdafx.h"
#define EXPORTING_DLL
#include "sampleDLL.h"
#include "pch.h"
#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    return TRUE;
}

void __stdcall HelloWorld()
{
    MessageBox(NULL, TEXT("Hello World"), TEXT("In a DLL"), MB_OK);
}  

修正后的加载器代码

/* DLL Loader */
#include <windows.h>
#include <iostream>

// 匹配DLL中的函数签名:void返回值 + __stdcall调用约定
typedef void(__stdcall* f_HelloWorld)();

int main()
{
    // 使用宽字符版本LoadLibraryW,替换为实际DLL路径
    HINSTANCE hGetProcIDDLL = LoadLibraryW(L"PATH\\LoadME.dll");

    if (!hGetProcIDDLL) {
        std::cout << "无法加载目标DLL" << std::endl;
        return EXIT_FAILURE;
    }

    f_HelloWorld HelloWorldFunc = (f_HelloWorld)GetProcAddress(hGetProcIDDLL, "HelloWorld");
    if (!HelloWorldFunc) {
        std::cout << "无法定位HelloWorld函数" << std::endl;
        FreeLibrary(hGetProcIDDLL);
        return EXIT_FAILURE;
    }

    // 调用函数,弹出MessageBox
    HelloWorldFunc();

    // 释放DLL资源
    FreeLibrary(hGetProcIDDLL);
    return EXIT_SUCCESS;
} 

内容的提问来源于stack exchange,提问作者torrid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 19:15:12