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;
}
.NET에서 메모리 누수가 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()
자체 호출이 충돌하지 않더라도 DLL은 나중에 .NET에 할당 된 로컬 pAMXFunctions
및 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()
크래시 문제가있는 경우 컴파일러의 디버거를 사용하여 런타임에 실제로 어떤 일이 발생하는지 알아 내야합니다. 지금까지 표시된 코드는 충돌하지 않아야합니다. 따라서 호출 규칙 불일치, 데이터 정렬 불일치, 메모리 손상 등이 있습니다. 디버거를 실행할 수 없습니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다