如何正确使用_beginthread和endthread [英] How to properly use _beginthread and endthread

查看:1053
本文介绍了如何正确使用_beginthread和endthread的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我曾经使用过良好的旧WinAPI调用CreateThread(),并使用等待功能(例如WaitForSingleObject())检查线程的状态,一旦用WAIT_OBJECT_0发出线程线程信号,我便使用CloseHandle().关闭它

I'm used to work with good old WinAPI call CreateThread(), and check thread's status using the waiting function, e.g WaitForSingleObject(), Once thread thread is signaled with WAIT_OBJECT_0, i close it using CloseHandle().

最近,我决定转到beginthread,以某种方式避免未初始化的crt以及可能发生的意外内存泄漏的风险.

Recently I've decided to move to beginthread and somehow avoid the risks of uninitialized crt and accidental memory leaks that may happen.

这样做使我感到困惑.

  1. endthread()的确切目的是什么?为什么在线程执行后,我在主函数中调用CloseHandle()时,CloseHandle()崩溃并带有无效句柄?
  2. 我应该关闭beginthread返回的句柄吗?
  3. endthread,据我了解,一旦函数超出范围,线程就会自动调用它,所以我应该在超出范围之前调用它吗?
  4. 根据msdn,endthread已调用CloseHandle() 1.线程从哪里获取对其句柄的引用/实例. 2.如果我确实坚持使用endthread(),它应该是线程中的最后一个命令吗?
  1. What's the exact purpose of endthread()? why when i call CloseHandle() in the main function, after thread's execution, CloseHandle() crashes with invalid handle?
  2. Should i ever close the handle returned by beginthread?
  3. endthread, As i understood is invoked automatically by the thread once my function goes out of scope, so should i call it anyway just before i get out of scope?
  4. According to msdn, endthread already calls CloseHandle() 1.From where does the thread obtain a reference / instance to its handle. 2. If i do insist on using endthread(), should it be the last command in the thread?

谢谢

编辑:描述泄漏的MSDN论文,此处.

MSDN paper describing the leaks, here.

推荐答案

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

As stated in the comments by David Hefferman you can simply change your code back to using CreateThread. The Visual C++ runtime (CRT) will automatically initialize the CRT's per thread data the first time you use a function that uses the per thread data.

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

The CRT will also automatically free the per thread data when a thread ends, so using CreateThread won't cause memory leaks. There is one exception, if all of the following conditions are true then per thread data isn't automatically freed:

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

请注意,即使您遇到的所有情况都是如此,除非您要创建一个寿命长的应用程序,该应用程序会在其生命周期内创建并销毁成千上万个线程,否则内存泄漏不会变得很重要.

Note that even if all this true in your case, the memory leak isn't going to be significant unless you're creating a long lived application that creates and destroys hundreds of thousands of threads over its life time.

如果您仍要使用CRT线程创建功能(_beginthread/_beginthreadex),则应遵循以下准则:

If you still want to use the CRTs thread creation functions (_beginthread/_beginthreadex) you should follow these guidelines:

  • 切勿使用_beginthread返回的句柄.使用_beginthread时,线程退出时线程句柄将自动关闭,这可能在_beginthread甚至返回之前发生.您不能安全地将其与WaitForSingleObject一起使用,因为在调用此函数之前该线程可能已经退出.如果您想将线程句柄用于任何用途,请改用_beginthreadex.
  • 永远不要关闭_beginthread返回的句柄. CRT将自动执行此操作,并且如前所述,它可能会在您有机会之前自动执行.
  • 当不再需要_beginthreadex返回的句柄时,应始终关闭它. CRT不会自动为您执行此操作,因此这是您自己的责任.
  • 请勿调用_endthread_endthreadex,除非您要快速且异常地终止线程.尽管CRT将释放其自己的每个线程数据,但不会调用该线程的任何对象的C ++析构函数.它的行为类似于_exit在不调用析构函数的情况下结束进程的方式.
  • 结束线程的通常方法是从作为参数传递给_beginthread_beginthreadex的函数中返回.这将导致C ++析构函数作为函数返回的正常部分被调用.
  • Never use the handle returned by _beginthread. With _beginthread the thread handle is automatically closed when the thread exits, which can potentially happen before _beginthread even returns. You can't use it with WaitForSingleObject safely because the thread might have already exited before you call this function. If you want to use the thread handle for anything use _beginthreadex instead.
  • You should never close the handle returned by _beginthread. The CRT will do it automatically, and as described in the previous point, may do so before you have chance to.
  • You should always close the handle returned by _beginthreadex when you no longer need it. The CRT won't do this automatically for you, so it's your own responsibility.
  • Don't call _endthread or _endthreadex unless you want to quickly and abnormally terminate the thread. While the CRT will free its own per thread data, none of the C++ destructors for any of the thread's objects will be called. It behaves similarly to how _exit ends the process without calling destructors.
  • The normal means of ending a thread should be by returning from the function passed as an argument to _beginthread or _beginthreadex. This will result in C++ destructors being called as a normal part of the function return.

这篇关于如何正确使用_beginthread和endthread的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆