我在这里有一个简单的测试用例(C ++),它负责LoadLibrary,GetProcAddress&调用函数(ProcAdd)。 签名是" char * ProcAdd(char *)"。
现在我确实在可执行文件中正确获取了字符串,但是一旦我做了#34; FreeLibrary",它已经消失了......(显然是因为我刚回来了#34;你好&# 34。)
问题是,我有另一个dll(.NET,C#),签名是" [return:MarshalAs LPSTR] string ProcAdd([MarshalAs LPSTR] string)"。 现在这个函数也返回一个字符串,但是当我执行" FreeLibrary"时,仍然可以在我的可执行文件中访问该字符串?!
这是怎么来的,我怎么能模仿同样的行为呢? (是的,我知道我可以将它存储在另一个变量中,但我想了解发生了什么以及如何重现这种.NET行为)。
非常感谢!
按要求提供代码:
C ++ exe:
int main( void )
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
void * val = NULL;
// Get a handle to the DLL module.
// hinstLib = LoadLibrary(TEXT("C:\\Users\\steven\\temp\\myMyMy.orig.dll"));
hinstLib = LoadLibrary(TEXT("C:\\Users\\steven\\temp\\myMyMy.proxy.dll"));
// If the handle is valid, try to get the function address.
if (hinstLib != NULL)
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "ProcAdd");
// If the function address is valid, call the function.
if (NULL != ProcAdd)
{
fRunTimeLinkSuccess = TRUE;
val = (ProcAdd) ("0987654321");
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
// If unable to call the DLL function, use an alternative.
if (! fRunTimeLinkSuccess)
printf("Message printed from executable\n");
return 0;
}
C ++ dll:
#include <Windows.h>
#include <iostream>
#include <fstream>
static const char tmp[] = "hello";
extern "C" const char * __stdcall ProcAdd(const char * param1) {
FILE * fp = fopen("C:\\tmp\\ProcAdd.txt", "a");
if ( fp ) {
fprintf(fp, "param1: '%s'\r\n", param1);
fclose(fp);
}
// return strdup("hello");
// return "hello";
return tmp;
}
C#dll:
[return: MarshalAs(UnmanagedType.LPStr)]
public static string ProcAdd([MarshalAs(UnmanagedType.LPStr)] string param1)
{
string str;
try
{
str = new WebClient().DownloadString("http://www.salvania.be/test.php?param1=" + param1);
}
catch (Exception exception1)
{
str = "Error-DLL";
}
return str;
}
工作回报:
// http://stackoverflow.com/questions/14406818/heapcreate-and-heapalloc-confuse
HANDLE winHandle = HeapCreate( 0, sizeof(tmp), sizeof(tmp) );
char* s = (char*)HeapAlloc( winHandle, 0, sizeof(tmp) + 1 );
strcpy((char*)s, tmp);
s[sizeof(tmp)] = 0;
答案 0 :(得分:1)
如果您只是return "hello"
,那个hello字符串可能来自共享库的数据段,并且可能在库的生命周期后卸载。
要确保在库的生命周期之后返回的字符串存在,您可以将其存储在堆上,或者以其他方式从调用者那里提供缓冲区。