_ Beginthread or createthread)

Source: Internet
Author: User
Tags strtok vc runtime

ProgramIt has been controversial whether _ beginthread or createthread should be used to create threads in Windows programs. This article will referSource codeTo discuss this issue.

I. Cause

Today, a friend asked me whether _ beginthread or createthread should be used in the program, and told me that there may be Memory leakage if used improperly. In fact, I used to understand this problem. In order to be responsible to my friends, I read the VC Runtime Library (CRT) source.CodeAnd finally found the answer.

Ii. CRT

CRT (C/C ++ Runtime Library) is a general term for a series of functions and code that support running C/C ++. Although there is no very precise definition, you can know that your main is called by it, the functions you call, such as strlen, strtok, time, and atoi, are also provided. Take the CRT attached to Microsoft Visual. NET 2003 as an example. If your. NET 2003 is installed in C: Program filesmicrosoft Visual Studio. NET 2003, the source code of the CRT is in C: Program filesmicrosoft Visual Studio. NET 2003vc7crtsrc. With the source code of these implementations, We can find all the explanations.

Iii. _ beginthread/_ endthread

What exactly has this function done? Its code is in thread. C. After reading the code, we can see that it eventually creates a thread through createthread. The main difference is that it first allocates a _ tiddata, the _ initptd is called to initialize the allocated pointer. The pointer will be passed to the CRT thread packaging function _ threadstart, where the pointer will be saved as a TLS (Thread Local Storage. Then _ threadstart will call the passed-in thread function and call _ endthread after the function exits. Here, we can also see that _ threadstart uses a _ Try/_ blocks to package our function and calls exit to exit when an exception occurs. (The _ threadstart and endthread code are both in thread. C)
What kind of structure is this _ tiddata? It is in mtdll. h, whose members are used by many CRT functions, such as int _ terrno, which is the error mark in this thread; char * _ token, since strtok, this variable records cross-function call information ,....
So what does _ endthread do? Besides the floating point clearing code, it also calls _ freeptd to release tiddata related to this thread. That is to say, the memory allocated in _ beginthread and the memory allocated and recorded in the memory structure in other CRT functions during thread running are released here.
Through the above code, we can see that if I use the _ beginthread function to create a thread, it will create everything required by the CRT function for me, and at last I don't have to worry about it, the cleanup can be done well. The only thing you need to note is that if you need to terminate the thread in advance, it is best to call _ endthread or return instead of calling exitthread, this may cause incomplete memory release. At the same time, we can also see that if we use the createthread function to create a thread and do not call the C Runtime Library (including any indirect call), we don't have to worry about any issues.

Iv. createthread and CRT

Some people may say that after I use createthread to create a thread, I also called the C Runtime Library Function and used exitthread to exit, but my program runs well, there was no crash because the CRT was not initialized, and there was no memory leakage because the _ endthread was forgotten. Why? Let's continue our CRT journey.
Suppose I use createthread to create a thread, and I call the strtok function for string processing, this function must be supported by some additional runtime. The source code of strtok is in strtok. C. As you can see from the Code, in the case of multithreading, the first valid Code of strtok is _ ptiddata PTD = _ getptd (), which obtains the current PTD through this. But we didn't create PTD through _ beginthread, so it must be _ getptd. Open tidtable. C and you can see the implementation of _ getptd. It first tries to obtain the current PTD. If it cannot, it creates a new one. Therefore, subsequent CRT calls will be safe. But who finally released the PTD? Open dllcrt0.c and you can see a dllmain function. In VC, CRT can be used either as a dynamic link library or as a static link to the main program. This can be selected in project setting-> code generations. When CRT is linked to the main program as a DLL, dllmain is the entry of crt dll. Windows dllmain can be called for four reasons: Process attach/process detach/thread attach/thread detach. The last one is when the thread function exits but the thread has not been destroyed, we will use thread detach to call dllmain in the context of this thread. Here, CRT implements a _ freeptd (null), that is, if there is PTD, it will be free. Therefore, the memory leakage happens because you are using a dynamic link CRT.
So we come to a more accurate conclusion that if I didn't use the CRT functions that would use _ getptd, it would be safe to use createthread.

V. Use the PTD Function

So what exactly are the functions using _ getptd? A lot! Search for _ getptd In the CRT directory, and you will find that many unexpected functions use it. In addition to strtok, Rand, and other functions related to string, because they need to use Locale information in PTD; All MBCS functions, because they need to use the MBCS information in PTD ,....

Vi. Test code

The following is a piece of test code (atoi is used by leaker, which requires PTD ):

# Include <windows. h>
# Include <process. h>
# Include <iostream>
# Include <crtdbg. h>

Volatile bool threadstarted = false;

Void leaker ()
{
STD: cout <atoi ("0") <STD: Endl;
}

DWORD _ stdcall createthreadfunc (lpvoid)
{
Leaker ();
Threadstarted = false;
Return 0;
}

DWORD _ stdcall createthreadfuncwithenderson thread (lpvoid)
{
Leaker ();
Threadstarted = false;
_ Endthread ();
Return 0;
}

Void _ cdecl beginthreadfunc (lpvoid)
{
Leaker ();
Threadstarted = false;
}

Int main ()
{
For (;;)
{
While (threadstarted)
Sleep (5 );
Threadstarted = true;
// _ Beginthread (beginthreadfunc, 0, 0); // 1
Createthread (null, 0, createthreadfunc, 0, 0); // 2
// Createthread (null, 0, createthreadfuncwithenderson thread, 0, 0, 0); // 3
}
Return 0;
}

If you use the multi-thread + static link CRT option of VC to compile this program and try to open a line in 1, 2, and 3, you will find that only 2 is enabled, the program will cause memory leakage (you can obviously observe it in the task manager ). 3. The reason why Memory leakage does not occur is because _ endthread is actively called.

VII. Summary

If you use the DLL-connected CRT library, or you only create a small number of threads at a time, you may be able to adopt the ostrich policy to ignore this issue. In the code above, the 3rd methods are based on the knowledge of the CRT library, but it is not guaranteed that this is a good method, because the CRT of each version of VC may be changed. It seems that unless your mind is clear enough to remember all this, or you can check the CRT code every time you call a C function, otherwise, it is a good choice to always use _ beginthread (or its brother _ beginthreadex.

[Postscript]
Condor pointed out an error in this article: In dllcrt0.c, the PTD released by thread detach of dllmain is actually created by thread attach in dllmain of dllcrt0.c. That is to say, when you use crt dll, dllmain initializes/clears the thread. I checked the source code and checked the _ threadstart function in thread. C before setting TLS. This is actually to avoid Memory leakage caused by repeated settings.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.