我一直在尝试使用GetProcAddress函数调用外部函数,但每次调用该函数时都会崩溃控制台,我一直在寻找但是在每个帖子中我得到相同的最终解决方案但是当我在我的DLL中尝试它时崩溃了应用程序。
以下是代码:
#include <Windows.h>
#include <vector>
#include "SDK\plugin.h"
typedef void (*logprintf_t)(char* format, ...);
logprintf_t logprintf;
// static void* m_AMXExports[44];
typedef bool (PLUGIN_CALL *ServerPluginLoad_t)(void **data);
typedef void (PLUGIN_CALL *ServerPluginUnload_t)();
typedef unsigned int (PLUGIN_CALL *ServerPluginSupports_t)();
typedef void (PLUGIN_CALL *ServerPluginProcessTick_t)();
typedef int (PLUGIN_CALL *ServerPluginAmxLoad_t)(AMX *amx);
typedef int (PLUGIN_CALL *ServerPluginAmxUnload_t)(AMX *amx);
struct Plugins
{
void* AppData[256];
SUPPORTS_FLAGS FlagSupport;
HMODULE Module;
ServerPluginLoad_t LOAD;
ServerPluginUnload_t UNLOAD;
ServerPluginSupports_t SUPPORTS;
ServerPluginProcessTick_t PROCESSTICK;
// AMX Plugin Interface
ServerPluginAmxLoad_t AMXLOAD;
ServerPluginAmxUnload_t AMXUNLOAD;
};
Plugins* ServerPlugins;
void **ppPluginData ;
extern void *pAMXFunctions;
//native LoadLibrary(libraryname[]);
static cell AMX_NATIVE_CALL my_LoadLibrary(AMX* amx, cell* params)
{
bool validfunc = false;
char *path;
amx_StrParam(amx, params[1], path);
logprintf("Loading plugin %s", path);
ServerPlugins = new Plugins();
ServerPlugins->Module = LoadLibraryA(path);
if (ServerPlugins->Module == NULL)
{
delete ServerPlugins;
logprintf("Failed loading plugin %s (Error: %d)", path, GetLastError());
return 0;
}
logprintf("NULL");
ServerPlugins->LOAD = (ServerPluginLoad_t)GetProcAddress(ServerPlugins->Module, "Load");
ServerPlugins->UNLOAD = (ServerPluginUnload_t)GetProcAddress(ServerPlugins->Module, "Unload");
ServerPlugins->SUPPORTS = (ServerPluginSupports_t)GetProcAddress(ServerPlugins->Module, "Supports");
if (ServerPlugins->LOAD == NULL || ServerPlugins->SUPPORTS == NULL || ServerPlugins->UNLOAD == NULL)
{
logprintf(" Plugin doesnt conform to architecture");
FreeLibrary(ServerPlugins->Module);
delete ServerPlugins;
return false;
}
logprintf("NULL 1");
ServerPlugins->FlagSupport = (SUPPORTS_FLAGS)ServerPlugins->SUPPORTS();
if ((ServerPlugins->FlagSupport & SUPPORTS_VERSION_MASK) > SUPPORTS_VERSION)
{
logprintf("Unsupported Version; unloading.");
FreeLibrary(ServerPlugins->Module);
delete ServerPlugins;
return false;
}
logprintf("NULL 2");
if ((ServerPlugins->FlagSupport & SUPPORTS_AMX_NATIVES) > SUPPORTS_VERSION)
{
ServerPlugins->AMXLOAD = (ServerPluginAmxLoad_t)GetProcAddress(ServerPlugins->Module, "AmxLoad");
ServerPlugins->AMXUNLOAD = (ServerPluginAmxUnload_t)GetProcAddress(ServerPlugins->Module, "AmxUnload");
}
else
{
ServerPlugins->AMXLOAD = NULL;
ServerPlugins->AMXUNLOAD = NULL;
logprintf("Any Abstract Machine has been loaded");
}
logprintf("NULL 3");
if ((ServerPlugins->FlagSupport & SUPPORTS_PROCESS_TICK) != 0)
{
ServerPlugins->PROCESSTICK = (ServerPluginProcessTick_t)GetProcAddress(ServerPlugins->Module, "ProcessTick");
}
else
{
ServerPlugins->PROCESSTICK = NULL;
}
logprintf("NULL 4"); //debugging
ServerPlugins->AppData[PLUGIN_DATA_AMX_EXPORTS] = pAMXFunctions;
ServerPlugins->AppData[PLUGIN_DATA_LOGPRINTF] = &logprintf;
if (!(ServerPlugins->LOAD)(ServerPlugins->AppData)) //i didnt put it as &ServerPlugins->AppData because it causes an error
{
logprintf("Initialized failed loading plugin %s", path);
FreeLibrary(ServerPlugins->Module);
logprintf("NULL 5");
delete ServerPlugins;
return false;
}
logprintf("Plugin %s loaded", path);
return true;
}
//native UnloadLibrary(libraryname[]);
static cell AMX_NATIVE_CALL my_UnloadLibrary(AMX*amx, cell*params)
{
char *path;
amx_StrParam(amx, params[1], path);
ServerPlugins->Module = GetModuleHandle((LPCTSTR)path);
if (ServerPlugins->Module != NULL)
{
ServerPlugins->UNLOAD = (ServerPluginUnload_t)GetProcAddress(ServerPlugins->Module, "Unload");
if (ServerPlugins->UNLOAD != NULL)
{
ServerPlugins->UNLOAD();
FreeLibrary(GetModuleHandleA(path));
logprintf("Library %s has been unloaded correctly", path);
return 1;
}
else
{
logprintf("Unloading library %s failed (Error: %d)", GetLastError());
return 0;
}
}
return 1;
}
PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData)
{
pAMXFunctions = ppData[PLUGIN_DATA_AMX_EXPORTS];
logprintf = (logprintf_t)ppData[PLUGIN_DATA_LOGPRINTF];
return 1;
}
PLUGIN_EXPORT void PLUGIN_CALL Unload()
{
}
PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports()
{
return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}
AMX_NATIVE_INFO projectNatives[] =
{
{ "LoadLibrary", my_LoadLibrary },
{ "UnloadLibrary", my_UnloadLibrary }
};
PLUGIN_EXPORT int PLUGIN_CALL AmxLoad(AMX *amx)
{
return amx_Register(amx, projectNatives, -1);
}
PLUGIN_EXPORT int PLUGIN_CALL AmxUnload(AMX *amx)
{
return AMX_ERR_NONE;
}
答案 0 :(得分:0)
convertCharArrayToLPCWSTR()
中有内存泄漏。您永远不会释放您分配的wchar_t*
。不需要convertCharArrayToLPCWSTR()
函数本身,您可以简单地将char*
路径原样传递给LoadLibraryA()
:
char *path;
amx_StrParam(amx, params[1], path);
...
ServerPlugins->Module = LoadLibraryA(path);
您没有检查ServerPlugins->UNLOAD
是否成功加载了GetProcAddress("Unload")
。
您对GetProcAddress("Load")
和ServerPlugins->LOAD
使用ServerPlugins->AMXLOAD
,GetProcAddress("Unload")
和ServerPlugins->UNLOAD
使用ServerPlugins->AMXUNLOAD
。这对我来说非常可疑。 DLL是否真的对AMX和非AMX入口点使用相同的导出?如果是这样,那么设计非常糟糕,因为ServerPluginLoad_t
的签名与ServerPluginAmxLoad_t
的签名截然不同,ServerPlugin(Amx)Unload_t
的签名也相同。这是一个等待发生的损坏的调用堆栈。让DLL导出单独的AmxLoad()
和AmxUnload()
函数会更安全。
就此而言,SUPPORTS_AMX_NATIVES
和SUPPORTS_PROCESS_TICK
标志是多余的,因为GetProcAddress()
会告诉您这些导出是否可用。
至于调用ServerPlugins->LOAD
时的崩溃,我没有看到您在将ppData
传递给Load()
之前使用任何数据初始化PLUGIN_DATA_AMX_EXPORTS
。当然不是PLUGIN_DATA_LOGPRINTF
和ppData[PLUGIN_DATA_AMX_EXPORTS] = pAMXFunctions;
ppData[PLUGIN_DATA_LOGPRINTF] = &logprintf;
if (!(ServerPlugins->LOAD)(ppData))
广告位,至少是:
Load()
因此,即使对pAMXFunctions
本身的调用没有崩溃,DLL也会在以后尝试使用其本地logprintf
和Load()
指针时崩溃。在void*
中分配。
就此而言,为什么要将这样的内容传递为struct
数组而不是struct PluginInitData
{
void* pAMXFunctions;
logprintf_t logprintf;
...
};
typedef bool (__stdcall *ServerPluginLoad_t)(PluginInitData* data);
PluginInitData pInitData;
pInitData.pAMXFunctions = pAMXFunctions;
pInitData.logprintf = &logprintf;
...
if (!(ServerPlugins->LOAD)(&pInitData))
?那会更安全,例如:
extern "C" bool __stdcall Load(PluginInitData* data)
{
pAMXFunctions = data->pAMXFunctions;
logprintf = data->logprintf;
...
return true;
}
my_UnloadLibrary()
更新:您已修复我提到的大部分问题,但现在我发现您的GetModuleHandle()
功能实施错误。 不要完全致电GetProcAddress()
或Module
,使用UNLOAD
中之前初始化的现有my_LoadLibrary()
和static cell AMX_NATIVE_CALL my_LoadLibrary(AMX* amx, cell* params)
{
char *path;
amx_StrParam(amx, params[1], path);
...
ServerPlugins->Path = path;
...
}
static cell AMX_NATIVE_CALL my_UnloadLibrary(AMX*amx, cell*params)
{
if (ServerPlugins)
{
if (ServerPlugins->UNLOAD != NULL)
ServerPlugins->UNLOAD();
if (ServerPlugins->Module != NULL)
{
FreeLibrary(ServerPlugins->Module);
ServerPlugins->Module = NULL;
}
logprintf("Library %s has been unloaded", ServerPlugins->Path);
delete ServerPlugins;
ServerPlugins = NULL;
}
return 1;
}
指针。
Load()
如果您仍然遇到{{1}}崩溃的问题,那么您将不得不使用编译器的调试器来查找运行时实际发生的情况。到目前为止显示的代码不应该崩溃,因此要么您具有调用约定不匹配,要么数据对齐不匹配,或内存损坏,或类似的东西。我们无法为您运行调试程序。