繁体   English   中英

如何正确使用_beginthread和endthread

[英]How to properly use _beginthread and endthread

我习惯使用旧的WinAPI调用CreateThread() ,并使用等待函数检查线程的状态,例如WaitForSingleObject() ,一旦用WAIT_OBJECT_0发信号通知线程线程,我使用CloseHandle().关闭它CloseHandle().

最近,我决定搬到beginthread并以某种方式避免未初始化CRT和可能发生的意外内存泄漏的风险。

这样做让我很困惑。

  1. endthread()的确切目的是什么? 为什么当我在main函数中调用CloseHandle()时,在执行线程后, CloseHandle()因无效句柄而崩溃?
  2. 我应该关闭beginthread返回的beginthread吗?
  3. endthread ,正如我endthread ,一旦我的函数超出范围,线程会自动调用,所以我应该在我超出范围之前调用它吗?
  4. 根据msdn,endthread已经调用了CloseHandle() 1.从哪里线程获得其句柄的引用/实例。 2.如果我坚持使用endthread() ,它应该是线程中的最后一个命令吗?

谢谢

编辑: 这里描述泄漏的MSDN论文。

正如David Hefferman的评论中所述,您只需将代码更改回使用CreateThread即可。 第一次使用使用每线程数据的函数时,Visual C ++运行时(CRT)将自动初始化CRT的每个线程数据。

当线程结束时,CRT也会自动释放每线程数据,因此使用CreateThread不会导致内存泄漏。 有一个例外,如果满足以下所有条件,那么每个线程数据不会自动释放:

  • 您正在构建可执行文件,而不是DLL
  • 您正在链接CRT库的静态版本(LIBCMT.LIB)而不是DLL版本(MSVCRT.LIB)
  • 您构建的可执行文件在Windows XP(或Windows的早期版本)下运行。

请注意,即使在您的情况下所有这一切都是正确的,除非您创建一个长期存在的应用程序,在其生命周期内创建并销毁数十万个线程,否则内存泄漏不会很重要。

如果您仍想使用CRTs线程创建函数( _beginthread / _beginthreadex ),您应该遵循以下准则:

  • 切勿使用_beginthread返回的句柄。 使用_beginthread ,线程句柄会在线程退出时自动关闭,这可能会在_beginthread返回之前发生。 您无法安全地将它与WaitForSingleObject一起使用,因为在调用此函数之前线程可能已经退出。 如果你想使用线程句柄来代替_beginthreadex
  • 您永远不应该关闭_beginthread返回的句柄。 CRT将自动执行,并且如前所述,可能会在您有机会之前执行此操作。
  • 当您不再需要时,应始终关闭_beginthreadex返回的句柄。 CRT不会自动为您执行此操作,因此这是您自己的责任。
  • 除非您想快速异常地终止线程,否则不要调用_endthread_endthreadex 虽然CRT将释放其自己的每个线程数据,但不会调用任何线程对象的C ++析构函数。 它的行为类似于_exit在不调用析构函数的情况下结束进程的方式。
  • 结束线程的常规方法应该是从作为参数传递的函数返回到_beginthread_beginthreadex 这将导致C ++析构函数被调用为函数返回的正常部分。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM