简体   繁体   English

如何正确使用_beginthread和endthread

[英]How to properly use _beginthread and endthread

I'm used to work with good old WinAPI call CreateThread() , and check thread's status using the waiting function, eg WaitForSingleObject() , Once thread thread is signaled with WAIT_OBJECT_0 , i close it using CloseHandle(). 我习惯使用旧的WinAPI调用CreateThread() ,并使用等待函数检查线程的状态,例如WaitForSingleObject() ,一旦用WAIT_OBJECT_0发信号通知线程线程,我使用CloseHandle().关闭它CloseHandle().

Recently I've decided to move to beginthread and somehow avoid the risks of uninitialized crt and accidental memory leaks that may happen. 最近,我决定搬到beginthread并以某种方式避免未初始化CRT和可能发生的意外内存泄漏的风险。

Doing that got me confused. 这样做让我很困惑。

  1. What's the exact purpose of endthread() ? endthread()的确切目的是什么? why when i call CloseHandle() in the main function, after thread's execution, CloseHandle() crashes with invalid handle? 为什么当我在main函数中调用CloseHandle()时,在执行线程后, CloseHandle()因无效句柄而崩溃?
  2. Should i ever close the handle returned by beginthread ? 我应该关闭beginthread返回的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? endthread ,正如我endthread ,一旦我的函数超出范围,线程会自动调用,所以我应该在我超出范围之前调用它吗?
  4. According to msdn, endthread already calls CloseHandle() 1.From where does the thread obtain a reference / instance to its handle. 根据msdn,endthread已经调用了CloseHandle() 1.从哪里线程获得其句柄的引用/实例。 2. If i do insist on using endthread() , should it be the last command in the thread? 2.如果我坚持使用endthread() ,它应该是线程中的最后一个命令吗?

thanks 谢谢

EDIT: MSDN paper describing the leaks, here . 编辑: 这里描述泄漏的MSDN论文。

As stated in the comments by David Hefferman you can simply change your code back to using CreateThread. 正如David Hefferman的评论中所述,您只需将代码更改回使用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. 第一次使用使用每线程数据的函数时,Visual C ++运行时(CRT)将自动初始化CRT的每个线程数据。

The CRT will also automatically free the per thread data when a thread ends, so using CreateThread won't cause memory leaks. 当线程结束时,CRT也会自动释放每线程数据,因此使用CreateThread不会导致内存泄漏。 There is one exception, if all of the following conditions are true then per thread data isn't automatically freed: 有一个例外,如果满足以下所有条件,那么每个线程数据不会自动释放:

  • You're building an executable, not a DLL 您正在构建可执行文件,而不是DLL
  • You're linking against the static version of the CRT library (LIBCMT.LIB) instead of the DLL version (MSVCRT.LIB) 您正在链接CRT库的静态版本(LIBCMT.LIB)而不是DLL版本(MSVCRT.LIB)
  • The executable you built is run under Windows XP (or an earlier version of Windows). 您构建的可执行文件在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. 请注意,即使在您的情况下所有这一切都是正确的,除非您创建一个长期存在的应用程序,在其生命周期内创建并销毁数十万个线程,否则内存泄漏不会很重要。

If you still want to use the CRTs thread creation functions ( _beginthread / _beginthreadex ) you should follow these guidelines: 如果您仍想使用CRTs线程创建函数( _beginthread / _beginthreadex ),您应该遵循以下准则:

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

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

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