在“FreeLibrary”之后将字符串值保留在内存中

时间:2014-09-27 17:37:15

标签: c++ string

我在这里有一个简单的测试用例(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;

1 个答案:

答案 0 :(得分:1)

如果您只是return "hello",那个hello字符串可能来自共享库的数据段,并且可能在库的生命周期后卸载。

要确保在库的生命周期之后返回的字符串存在,您可以将其存储在堆上,或者以其他方式从调用者那里提供缓冲区。