none
使用WINDOWS线程池时,工作线程能调用C/C++库函数吗? RRS feed

  • 问题

  • 线程池的工作线程是由WINDOWS启动的,在静态链接的情况下,这些线程不是通过_beginthread启动的,线程的C运行库没有初始化,线程结束时也没有调用_endthread清理C运行库。在这些线程中能安全地调用C库函数吗?会不会引起内存泄露之类的问题?如果不能,有无解决办法?

    2014年10月16日 2:44

答案

  • 你还是看一下这篇文章吧:blog.sina.com.cn/s/blog_680e2f5b0100y381.html,类似的内容在网上可以搜出很多。我现在疑惑的是WINDOWS POOL API创建的线程终止时如何通知C运行库。内存泄露之类的问题是很难检查出来的!

    你给的文章我仔细读过了,此问题出现在早期版本的 CRT 上,新的版本已经修复此问题,请考虑将你的项目升级到较高的版本。

    就你给出的文章中提到的 strtok函数,已经被废弃,请使用 strtok_s 替代,类似的其它函数都有 _SECURE_VERSION 版本可用。

    • 已标记为答案 pengjunpj 2014年10月21日 0:47
    2014年10月20日 3:47

全部回复

  • 我简单的回答一句,能!

    不同运行时涉及到的主要问题是内存分配和释放。

    2014年10月16日 3:19
  • 静态链接下,这样由WINDOWS自动创建的线程不会引起C运行时的内存泄露?
    2014年10月16日 5:18
  • 请问,WINDOWS是如何自动创建线程的?能否解析清楚点。

    2014年10月17日 2:52
  • 我也不知道WINDOWS是如何自动创建线程的,使用windows pool函数后,会为调用进程创建一个线程池,由WINDOWS负责创建与销毁池中的工作线程,具体细节没有公开。问题是WINDOWS创建与销毁线程时,如果是静态链接的话,C运行库如何初始化与销毁?会不会引起内存泄露?

    2014年10月17日 3:09
  • 你能把“使用windows pool函数”中的具体的 API 给贴出来吗?

    2014年10月17日 3:13
  • 最简单的:TrySubmitThreadpoolCallback这个函数向线程池提交一个工作任务,如果本进程还没有线程池,WINDOWS就为本进程自动创建一个线程池,然后自动创建一些线程调用我提交的工作任务函数。其它的线程池函数与此函数类似!!
    2014年10月17日 3:21
  • 然后你的程序静态链接到某个版本的 msvcr.dll ,是吗?如果是的话,我可以负责任的告诉你,不会存在内存泄漏。

    2014年10月17日 3:35
  • 关于跨 DLL 边界传递 CRT 对象可能引起的问题,请看这里:http://msdn.microsoft.com/zh-cn/library/ms235460.aspx

    2014年10月17日 3:37
  • 我说的静态链接是没有使用C运行库的DLL,直接生成一个不需要DLL的EXE,这和使用DLL的区别就是,创建和销毁线程时,没有DLLMAIN函数接收到通知,就无法初始化或释放C运行库使用的内存,可能引起内存泄露。运行库的设置成多线程调试(/mtd),就不需要程序启动时加载msvcr.dll,避免某些电脑没有VC运行时引起的麻烦。

    2014年10月17日 6:51
  • 我说的静态链接是没有使用C运行库的DLL,直接生成一个不需要DLL的EXE,这和使用DLL的区别就是,创建和销毁线程时,没有DLLMAIN函数接收到通知,就无法初始化或释放C运行库使用的内存,可能引起内存泄露。运行库的设置成多线程调试(/mtd),就不需要程序启动时加载msvcr.dll,避免某些电脑没有VC运行时引起的麻烦。

    还是看代码吧:

    VOID CALLBACK SimpleCallback(PTP_CALLBACK_INSTANCE Instance, PVOID Context)
    {
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	// 提交一个线程池任务
    	TrySubmitThreadpoolCallback(SimpleCallback, NULL);
    
    	getchar();
    	return 0;
    }

    此程序无论你以 /MT,/MTd,/MD,/MDd 设置来编译,都不存在你说的内存泄漏问题。

    再来看另一个实例,涉及到内存分配:

    struct SimpleContext
    {
    };
    
    VOID CALLBACK SimpleCallback(PTP_CALLBACK_INSTANCE Instance, PVOID Context)
    {
    	SimpleContext * pContext = static_cast<SimpleContext *>(Context);
    
    	// 在线程回调中释放
    	delete pContext;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	// 分配一个 CRT 对象
    	SimpleContext * pContext = new SimpleContext;
    
    	// 提交一个线程池任务
    	TrySubmitThreadpoolCallback(SimpleCallback, pContext, NULL);
    	
    	getchar();
    	return 0;
    }

    结论也是一样的,此程序无论你以 /MT,/MTd,/MD,/MDd 设置来编译,都不存在你说的内存泄漏问题。

    所以,我不明白你为啥会把 /MT,/MTd 同 DLLMAIN,以及 Windows Pool API 等结合起来得出是否引起内存泄漏的疑惑的。


    • 已编辑 Skyseer 2014年10月17日 8:16
    2014年10月17日 8:15
  • 你还是看一下这篇文章吧:blog.sina.com.cn/s/blog_680e2f5b0100y381.html,类似的内容在网上可以搜出很多。我现在疑惑的是WINDOWS POOL API创建的线程终止时如何通知C运行库。内存泄露之类的问题是很难检查出来的!
    2014年10月17日 14:33
  • 你还是看一下这篇文章吧:blog.sina.com.cn/s/blog_680e2f5b0100y381.html,类似的内容在网上可以搜出很多。我现在疑惑的是WINDOWS POOL API创建的线程终止时如何通知C运行库。内存泄露之类的问题是很难检查出来的!

    你给的文章我仔细读过了,此问题出现在早期版本的 CRT 上,新的版本已经修复此问题,请考虑将你的项目升级到较高的版本。

    就你给出的文章中提到的 strtok函数,已经被废弃,请使用 strtok_s 替代,类似的其它函数都有 _SECURE_VERSION 版本可用。

    • 已标记为答案 pengjunpj 2014年10月21日 0:47
    2014年10月20日 3:47