C ++ DLL中的线程安全字符串缓冲区变量

时间:2011-06-22 18:38:01

标签: c++ winapi dll string thread-safety

我正在使用导出的函数在MSVC ++ 2010中编写Win32 DLL。其中一些函数将文件名返回为LPCSTR。因为我以前有时需要摆弄字符串,所以我目前正在使用长度为32184的全局缓冲区变量,该变量应该覆盖Windows中可能出现的任何文件名,然后我总是初始化并返回需要字符串的地方。

我的老板在VB6遗留应用程序中使用此库。他现在告诉我他需要它是线程安全的:不幸的是,由于VB6的事件驱动行为,即使另一个函数尚未返回,也可能在我的库中调用函数。当然,这意味着我不能依赖单个内部缓冲区,但每次需要时都必须创建一个,然后返回它。

2个问题:

  1. 我在很大程度上依赖于FindFirstFilefilesystem库中的regex和Boost函数等Windows API函数。我可以假设它们都是线程安全的吗?

  2. 如果每次要返回一个字符串时都要在堆上创建一个新的缓冲区,我该在哪里再次释放内存?

3 个答案:

答案 0 :(得分:3)

  1. Windows API函数通常是线程安全的,但有一些限制(例如,你不能同时在两个线程的同一个句柄上FindNextFile,但你可以使用两个不同的句柄)。有关boost函数,请参阅文档,但一般来说,只要不同时在两个线程之间使用相同的对象,文件系统/正则表达式函数就应该是安全的。
  2. 完成后,您必须回拨VB6应用程序以释放字符串。您可能还想考虑将DLL编写为COM库;当不再需要时,VB6会自动释放从COM调用返回的BSTR。

答案 1 :(得分:1)

VB6代码很可能是单线程的。重新入门可能仅限于VB6代码。 VB6代码无法将重入事件注入C ++代码。只要C ++代码不回调到VB6代码,那么C ++代码本身就不会以可重入的方式被调用。

如果这些假设是正确的,那么具有单个全局缓冲区的当前代码将正确运行。这表示你最好在我的视图中切换到BSTR,因为它允许将来链接到多线程的调用者。

答案 2 :(得分:0)

您可以使用TLS分配字符串:



const int string_size = 1024; // string size 
DWORD idTlsString = 0;


// use this function to get the string which you will use to return to VB
char* GetTheString()
{
    return (char*)TlsGetValue(idTlsString);
}

// Dll init function
BOOL WINAPI DllMain(
  HINSTANCE hinstDLL,
  DWORD fdwReason,
  LPVOID lpvReserved
)
{
   switch( fdwReason )
   {
       // allocate TSL
       case DLL_PROCESS_ATTACH:
          idTlsString = TlsAlloc();
       break;

       // allocate the srting
       case DLL_THREAD_ATTACH:
          TlsSetValue(idTlsString, (LPVOID)new char[string_size] );
       break;

       // free the string
       case DLL_THREAD_DETACH:
          delete[] (char*)TlsGetValue(idTlsString);
       break;

       // release TLS
       case DLL_PROCESS_DETACH:
          TlsFree(idTlsString);
       break;

   }
   return true;
}