C ++ - 如何找出当前线程的创建位置?

时间:2015-12-30 15:08:26

标签: c++ multithreading visual-studio-2010 mfc

我正在使用Visual Studio 2010处理一个巨大的C ++ MFC GUI应用程序,这个应用程序有很多我不熟悉的代码。

有一个线程被生成的次数太多了,我不知道它在哪里产生,因为有很多代码产生了这个线程。此外,同一线程的代码中有许多创建点。我需要找到哪个创建点启动了当前的线程函数。

如何在Visual Studio中找到创建线程的位置?

注意:我无法看到在调用堆栈窗口中创建线程的位置。

2 个答案:

答案 0 :(得分:1)

如果可能的话,然后为用于创建线程的函数创建一个宏定义,那么一旦创建它,​​就会在一些map中创建存储线程id / handle,它将包含以下类型的对:[ThreadID] - > [__FILE__+__LINE__]。这将允许您在线程内部检查它的创建位置。

更高级的方法是使用api钩子,但这就是很多编码。因此,您可以使用api挂钩http://codefromthe70s.org/mhook22.aspx并挂钩CreateThread。执行自定义CreateThread函数后,您可以执行原始CreateThread并使用其返回的句柄更新第一段中的映射。问题是您必须存储callstack数据才能找到执行此调用的位置。您可以使用http://www.codeproject.com/Articles/11132/Walking-the-callstack

即使使用第一个解决方案,您可能会发现__FILE__+__LINE__没有提供足够的信息,并且必须使用callstack。

我用mhook制作了一个小测试应用程序 - 下面是一些可能有用的代码:

typedef HANDLE(WINAPI *CreateThread_t)(LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD);
CreateThread_t fCreateThread = (CreateThread_t)GetProcAddress(LoadLibrary(L"Kernel32.dll"), "CreateThread");

HANDLE
WINAPI
MyCreateThread(
  _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_ SIZE_T dwStackSize,
  _In_ LPTHREAD_START_ROUTINE lpStartAddress,
  _In_opt_ __drv_aliasesMem LPVOID lpParameter,
  _In_ DWORD dwCreationFlags,
  _Out_opt_ LPDWORD lpThreadId
  )
{
  HANDLE hret = fCreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
  // Here you can add thread entry for hret with current callstack.
  // You will probably want to create this thread suspended, to make
  // sure it wont get executed before map gets updated. Resume it after
  // map update.
  //if (lpStartAddress == MyThreadProcToMonitor) {
    // log things
  //}
  return hret;
}

int main() {
// This will hook create thread
  Mhook_SetHook((PVOID*)&fCreateThread, MyCreateThread);

  // App logic here

  Mhook_Unhook((PVOID*)&fCreateThread);
}

答案 1 :(得分:0)

如果允许稍微更改代码,您可以用宏来替换线程启动调用,该宏也会记录__FILE____LINE__和线程ID,以便您可以跟踪发布会。