Go CreateThread and _beginthread, why the memory leak because (the original post layout some bad, so I sort it out a little)

Source: Internet
Author: User
Tags strtok

when writing C + + code, always keep in mind a word: should never call CreateThread. You should use the Visual C + + run-time library function _beginthreadex. As if the CreateThread function is a tiger, so why should Microsoft develop this function?

do not create threads with CreateThread, and use CloseHandle to shut down this thread, because this leads to memory leaks and should be _beginthread to create threads and _endthread to destroy threads. In fact, the real reason is not so .

Because after CreateThread, the thread object is still in the system after the thread terminates, the thread object must be closed through the CloseHandle function. Why does it cause memory leaks? Because when the function of the thread is used in the standard library of C, it is easy to cause conflict, so when the project of VC is created, the system prompt is either single thread or multi-threaded library, because there are many global variables in C. such as errno.


Because there are global variables in the C library, it is easy to run unhealthy if the standard C library is used in the program. So, both Microsoft and Borland have made some improvements to C's library. One condition of this improvement, however, is that if a thread has already been created, a struct should be created to contain the global variables and then put these global variables into the context of the thread. As a result, global variables are dependent on this thread and do not cause conflicts.


There is a problem with this, when does this thread start to create? The standard C library is not known, and CreateThread is the operating system's API. So you need to use _beginthread/_endthread to create/end threads and get the standard C library ready for threading.


The global variables copied by the standard C library will not be released when the thread is created with _beginthread and the CloseHandle is closed, which is the reason for the memory leaks mentioned earlier.


On the other hand, if you use Createthread/closehandle to create/end threads, do not use any of the standard C library functions. It is also important to note that you should not use CloseHandle to end a thread until you finish executing it, otherwise there will be an exception. We usually wait for the thread to end through waitforsingleobject/waitformultipleobjects.

  the
     createthread function is the Windows function used to create the thread. However, you should never call CreateThread if you are writing a C + + code. Instead, you should use the visual   C + + run-time library function _beginthreadex. If you do not use Microsoft's visual   C + + compiler, your compiler vendor has its own createthred substitution function.    
      to enable multithreaded C and C + + programs to run correctly, you must create a data structure and associate it with each thread that uses the C + + run-time library function. When you call the C + + runtime library, these functions must know to look at the data blocks of the calling thread, so that they do not adversely affect other threads.   &NBSP
   1. Each thread obtains its own tiddata memory structure allocated by the stack of the C + + run-time library.    
   2. The address of the thread function passed to _beginthreadex is stored in the Tiddata memory block. The parameters passed to the function are also saved in the data block.    
   3._beginthreadex does invoke CreateThread internally because this is the only way the operating system knows how to create a new thread.    
   4. When calling Createtthread, it is told to start executing a new thread by calling _threadstartex instead of PFNSTARTADDR.        Also, the arguments passed to the thread function are tiddata structures rather than pvparam addresses.     5. If all goes well, it will return the thread handle like CreateThread.  If any operation fails, it returns NULL.
The difference between _beginthreadex and _beginthread functions. The _beginthread function has fewer parameters, so it is more restrictive than the _BEGINTHREADEX function, which is full of features.
For example, if you use _beginthread, you cannot create a new thread with a security attribute, you cannot create a suspended thread, and you cannot get the ID value of a thread.    CreateThread, _beginthread, and _beginthreadex are all used to start the thread, but you see Oldworm does not provide a _beginthread way, the reason is simple, _beginthread is _ Beginthreadex function subset, although _beginthread internal is called _beginthreadex but he shielded features such as security features, so _beginthread and CreateThread is not the same level, _ Beginthreadex and CreateThread are completely functionally replaceable, so let's compare _beginthreadex and createthread!

The CRT function library already existed before the thread appeared, so the original CRT could not really support threads, which led us to choose the CRT library when we were programming, and when we consulted the CRT functions in MSDN:
Libraries
LIBC. LIB single thread Static library, retail version
LIBCMT. LIB multithread Static Library, retail version
MSVCRT. LIB Import Library for MSVCRT. DLL, retail version
Such a hint!
Support for threads is a thing of the future!
This also led to many CRT functions in the case of multithreading must have special support, not easy to use CreateThread on OK.
Most CRT functions can be used in the CreateThread thread, to see that only the signal () function is not available, which will cause the process to terminate! But can be used not to say no problem!

Some CRT functions like malloc (), fopen (), _open (), Strtok (), CTime (), or localtime () require specialized thread-locally stored data blocks, which usually need to be established when creating a thread, if using CreateThread, this data block is not built, and then what happens? These functions can still be used in such a thread, and there is no error, in fact the function discovers that the pointer to the block is empty, builds one itself, and then ties it to the thread, which means that if you use CreateThread to create the thread, and then using such a function, There will be a piece of memory unknowingly created, unfortunately, these functions do not delete it, and CreateThread and ExitThread can not know this matter, so there will be memory Leak, the thread frequently launched in the software (such as some server software), Sooner or later, the system's memory resources will be exhausted!

_beginthreadex (internally also called CreateThread) and _endthreadex the memory block has been processed, so there is no problem! (no one will intentionally use the CreateThread to create and then terminate with _endthreadex, and the termination of the thread is best not to explicitly call the terminating function, naturally quit the best!) )

When it comes to handle's problem, _beginthread's corresponding function _endthread automatically calls CloseHandle, while _beginthreadex's corresponding function _endthreadex does not, So CloseHandle anyway is to invoke but _endthread can help you do not have to write, the other two need to write their own! (Jeffrey Richter strongly recommends that as far as possible without the explicit termination function, with the natural exit way, natural exit of course must write their own closehandle)main causes of memory leaks for threads

In many reference books, it is said that you should not use CreateThread to create threads and use CloseHandle to close this thread, because doing so will lead to memory leaks and should be _beginthread to create threads and _endthread to destroy threads. In fact, the real reason is not so.

Look at the following code:

HANDLE CreateThread

(

Lpsecurity_attributes lpthreadattributes,//thread-safe properties

DWORD dwstacksize,//Stack size

Lpthread_start_routine lpstartaddress,//thread function

LPVOID lpparameter,//thread parameters

DWORD dwcreationflags,//Thread creation properties

Lpdword Lpthreadid//thread ID

);

After the thread aborts running, the thread object is still in the system, and the thread object must be closed through the CloseHandle function.

The prototype of the CloseHandle function is:

BOOL CloseHandle (HANDLE hobject);//handle Hobject Object handle

CloseHandle can close many types of objects, such as file objects, and use this function to close the thread object. When called, Hobject is the handle to the thread object to be closed.

It is not entirely correct to say that there is a leak in this method. Then why does it cause a leak in memory? Because when the function of the thread is used in the standard library of C, it is easy to cause conflict, so when the project of VC is created, the system prompt is either single thread or multi-threaded library, because there are many global variables in C. For example, global variables such as error numbers, file handles, and so on.

Because there are global variables in the C library, when using the C library, if the standard C library is used in the program, it is very easy to run abnormally and cause a lot of conflicts. So, both Microsoft and Borland have made some improvements to C's library. One condition of this improvement, however, is that if a thread is already created, a struct should be created to contain the global variables, and then the global variables are put into the context of the thread and associated with the thread.  In this way, the global variable will be dependent on this thread and will not cause a conflict. There is a problem with this, when does this thread start to create? The standard Windows API is not known because it is a static library. These libraries are placed in the directory of the VC's lib, and the thread function is the function of the operating system. So, when the VC and BC create the thread, they use _beginthread to create the thread, and then use _endthread to end the thread.

This way, when they create a thread, they know when to create the thread and put the global variable into a structure so that it can be associated with the thread. So there will be no conflict.

Obviously, to complete this function, you first need to allocate the structure table to include the global variables. This process is done at _beginthread, and the release is done within the _endtread.

Therefore, when using _beginthread to create, and use CloseHandle to close the thread, then the replication of the global structure will not be released, there is a memory leak. This is the real reason why a lot of data is called a memory leak problem.

In fact, you can not _beginthread and _endthread this pair of functions.

If created with the CreateThread function and closed with CloseHandle, the libraries associated with C will be global, and they will cause conflicts. Therefore, a better approach is to use the standard C library within the thread (the library functions of the Windows API can be used). This will not be a problem, and it will not cause conflict. For example, string manipulation functions, file operations, and so on.

When a program creates a thread, a handle to the thread is generated, and the thread's handle is primarily used to control the operation of the entire thread, such as stopping, suspending, or setting the priority of the thread. In general, when a thread is enabled, it uses the thread's CloseHandle to close the thread.

But in Microsoft's example program, an example is created and is called immediately after the CloseHandle shutdown thread is run. This is fine under Windows 98, but under Windows NT, the kernel will get an error. What is this for?

This is because the thread-related structure has been freed, but the thread is still running, so the program will get an error.  What can be done to ensure normal operation?  In fact, to run normally, you can let the thread completely end and then call CloseHandle to release the resource. How do you know the thread is completely over? There is a class of wait-thread commands in the Windows API:

DWORD WaitForSingleObject

(

HANDLE Hhandle,//HANDLE to object to wait for

DWORD dwmilliseconds,//time-out interval in milliseconds

);

DWORD WaitForMultipleObjects

(

DWORD ncount,//number of handles in the handle array

CONST HANDLE *lphandles,//Pointer to the Object-handle array

BOOL fWaitAll,//wait flag

DWORD dwmilliseconds//time-out interval in milliseconds

);

You can use the above two functions to wait for the end of the thread. If the thread ends, the function returns.  Otherwise, wait until the specified time is over. There is also a thread that does not exit at all, and it runs a recurring thread. We're going to use the abort thread to end the thread and force it to close. Once forced to close, use CloseHandle to release the structure.

Audience:why use _beginthreadex () rather than CreateThread?

When you are going to implement a multithreaded (non-MFC) program, would you choose a single-threaded CRT (C run-time library)? If your answer is no, then there is another problem, have you chosen CreateThread to create a thread? Most people may answer yes right away. Unfortunately, this is the wrong choice.
I'll tell you what I'm going to say to you later.

If you want to make a multithreaded (non-MFC) program, any line outside the main thread range
-Using malloc (), Free (), new
-Call stdio.h or io.h, including fopen (), open (), GetChar (), write (), printf (), errno
-Use floating-point variables and floating-point arithmetic functions
-Call those functions that use static buffers such as: Asctime (), Strtok (), Rand (), and so on.
You should use a multithreaded CRT with _beginthreadex (the function exists only in a multithreaded CRT), and in other cases you can use a single-threaded CRT with CreateThread.

Because for the resulting thread, the _beginthreadex CreateThread will do extra bookkeeping for the above operations, such as helping Strtok () prepare a buffer for each thread.
However, multithreaded programs rarely use these functions (such as memory allocation or IO), so instead of thinking about whether to use _beginthreadex or createthread each time, it is better to finalize the _beginthreadex on a stick.

Of course you might be able to use Win32 to handle memory allocations and IO, and you can actually createthread with a single-threaded CRT, because the task of IO has been transferred from the CRT to the Win32. Usually you should use Heapalloc,heapfree to handle memory allocations, using CreateFile or getstdhandle to handle IO.

It is also important to note that although the _beginthreadex is a unsigned long, is actually a thread handle (in fact _beginthreadex in the interior is called CreateThread), So you should use CloseHandle to end him. Do not use ExitThread () to exit the thread created by _beginthreadex, which would lose the opportunity to release bookkeeping data and should use _endthreadex.

Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

To put it simply, when the thread ends abnormally, the thread created by _beginthread invokes the destructor of the variable on the stack, freeing the resource, and the thread created by CreateThread does not. Because CreateThread is the interface provided by the operating system, to be efficient, to speed, he does not know the stack of this thing, the unintentional processing of these, perhaps a language of memory mode and C + + is completely different, so CreateThread will not be able to control the C + + thing But in order to ensure consistency, the CRT is responsible for the destruction of C/s, so the CRT tube, encapsulated the enhanced CreateThread, ensure consistency.

Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Specifically, CreateThread This function is provided to the user by Windows API function, is the standard form of the SDK, in the process of use to take into account the process of synchronization and mutual exclusion of the relationship between the process of mutual exclusion and so on a series of causes of the operating system deadlock factors, used more cumbersome, Beginners in the use of the time may produce unpredictable errors, it is recommended to use AfxBeginThread, is the compiler to the original CreateThread function encapsulation, with MFC programming (of course, as long as the project properties modified, Both the console and the Win32 project can be called) and _beginthread is the run-Library function of C.

When using AfxBeginThread, the thread function is defined as: the UINT _yourthreadfun (LPVOID pparam) parameter must be so
When using CreateThread, the function of the thread is defined as: DWORD WINAPI _yourthreadfun (LPVOID pparameter).

The essence of the two is the same, but AfxBeginThread returns a CWinThread pointer, that is, he will be a new CWinThread object, and this object is automatically deleted (at the end of the thread run), the inconvenience to us is not to get its state, Because it's possible at any time this pointer is pointing to an already invalid memory area, so when used (if you need to know its health) first create_suspended let him hang, then M_bautodelete=false, then ResumeThread, Finally, don't delete that pointer.
Creatthread is more convenient, it returns a handle, if you do not use CloseHandle, you can safely understand the thread state, the last time Closehandle,windows will release resources, So I generally use creatthread, convenient.

If using MFC programming, do not use CreateThread, if just use the runtime Library, with _begingthread, in short, do not use CreateThread easily. This is because functions in MFC and RTL may use some of the common variables they encapsulate, meaning that both AfxBeginThread and _beginthread have their own startup code that CreateThread does not have.
It is possible to have problems using MFC's classes and RTL functions in threads created with CreateThread.
If you are using the assembly to write the Win32 program and do not call the MFC and RTL functions in the thread function, then use CreateThread is fine, or you are using the C write thread function, but you are careful not to call the RTL function is not a problem.
CreateThread is an interface provided by the operating system, while AfxBeginThread and _beginthread are the compiler's encapsulation of it.

If possible, do not call _beginthread, but should call _beginthreadex, and the corresponding _endthreadex. This is a C + + run-time function.
However, with _beginthread, you cannot create a new thread with a security attribute, you cannot create a paused thread, or you cannot get a thread id,_endthread, it does not take parameters,


This means that the exit code for this thread must be hard-coded to 0. The two functions are called in _beginthreadex and _endthreadex. CreateThread do not make a direct call.

Go CreateThread and _beginthread, why the memory leak because (the original post layout some bad, so I sort it out a little)

Related Article

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.