Windows threading: _beginthread vs _beginthreadex vs CreateThread C++

后端 未结 17 1266
臣服心动
臣服心动 2020-11-22 17:26

What\'s a better way to start a thread, _beginthread, _beginthreadx or CreateThread?

I\'m trying to determine what are the adv

相关标签:
17条回答
  • 2020-11-22 17:34

    Looking at the function signatures, CreateThread is almost identical to _beginthreadex.

    _beginthread, _beginthreadx vs CreateThread

    HANDLE WINAPI CreateThread(
      __in_opt   LPSECURITY_ATTRIBUTES lpThreadAttributes,
      __in       SIZE_T dwStackSize,
      __in       LPTHREAD_START_ROUTINE lpStartAddress,
      __in_opt   LPVOID lpParameter,
      __in       DWORD dwCreationFlags,
      __out_opt  LPDWORD lpThreadId
    );
    
    uintptr_t _beginthread( 
       void( *start_address )( void * ),
       unsigned stack_size,
       void *arglist 
    );
    
    uintptr_t _beginthreadex( 
       void *security,
       unsigned stack_size,
       unsigned ( *start_address )( void * ),
       void *arglist,
       unsigned initflag,
       unsigned *thrdaddr 
    );
    

    The remarks on here say _beginthread can use either __cdecl or __clrcall calling convention as start point, and _beginthreadex can use either __stdcall or __clrcall for start point.

    I think any comments people made on memory leaks in CreateThread are over a decade old and should probably be ignored.

    Interestingly, both _beginthread* functions actually call CreateThread under the hood, in C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\src on my machine.

    // From ~line 180 of beginthreadex.c
    /*
     * Create the new thread using the parameters supplied by the caller.
     */
    if ( (thdl = (uintptr_t)
          CreateThread( (LPSECURITY_ATTRIBUTES)security,
                        stacksize,
                        _threadstartex,
                        (LPVOID)ptd,
                        createflag,
                        (LPDWORD)thrdaddr))
             == (uintptr_t)0 )
    {
            err = GetLastError();
            goto error_return;
    }
    
    0 讨论(0)
  • 2020-11-22 17:34

    CreateThread() once was a no-no because the CRT would be incorrectly initialize/clean up. But this is now history: One can now (using VS2010 and probably a few versions back) call CreateThread() without breaking the CRT.

    Here is the official MS confirmation. It states one exception:

    Actually, the only function that should not be used in a thread created with CreateThread() is the signal() function.

    However, from consistence point of view, I personally prefer to keep using _beginthreadex().

    0 讨论(0)
  • 2020-11-22 17:36

    CreateThread() is the straight system call. It's implemented on Kernel32.dll which, most probably, your application will already be linked against for other reasons. It is always available in modern Windows systems.

    _beginthread() and _beginthreadex() are wrapper functions in the Microsoft C Runtime (msvcrt.dll). The differences between the two calls are stated in the documentation. It is thus available when the Microsoft C Runtime is available, or if your application is linked statically against it. You'll likely be linking against that library, too, unless you're coding in pure Windows API (as I personally often do).

    Your question is a coherent and actually a recurrent one. As many APIs, there are duplicate and ambiguous functionality in the Windows API we have to deal with. Worst of all, the documentation does not clarify the issue. I suppose that the _beginthread() family of functions was created for better integration with other standard C functionalities, such as the manipulation of errno. _beginthread() thus integrates better with the C runtime.

    Despite that, unless you have good reasons for using _beginthread() or _beginthreadex(), you should use CreateThread(), mostly because you might get one less library dependency in your final executable (and for MS CRT this does matter a bit). You also have no wrapping code around the call, although this effect is negligible. In other words, I believe that the main reason for sticking with CreateThread() is that there is no good reason to use _beginthreadex() to begin with. The functionalities are precisely, or almost, the same.

    One good reason to use _beginthread() would be (as it seems to be false) that C++ objects would be properly unwinded/destroyed if _endthread() was called.

    0 讨论(0)
  • 2020-11-22 17:36

    You should try this code

    #include<stdio.h>
    #include<stdlib.h>
    #include<windows.h>
    #include<process.h>
    
    UINT __stdcall Staff(PVOID lp){
     printf("The Number is %d\n", GetCurrentThreadId());
     return 0;
    }
    
    INT main(INT argc, PCHAR argv[])
    {
    
        const INT Staff_Number = 5;
        HANDLE hd[Staff_Number];
        for(INT i=0; i < Staff_Number; i++){
           hd[i] = (HANDLE)_beginthreadex(NULL, 0, Staff, NULL, 0, NULL);
        }
    
     WaitForMultipleObjects(Staff_Number, Staff, TRUE, NULL);
     for(INT i=0; i < Staff_Number; i++)
     {
         CloseHandle(hd[i]);
     }
     system("pause");
     return 0;
    }
    

    if you use _beginthread instead of _beginthreadex it will give error too many argument for _beginthread it is because _beginthread couldnt create a thread with security attribute and also i think _beginthread is unnecessary you can absolutely use *(_beginthreadex) and CreateThread

    0 讨论(0)
  • 2020-11-22 17:37

    In general, the correct thing to do is to call _beginthread()/_endthread() (or the ex() variants). However, if you use the CRT as a .dll, the CRT state will be properly initialized and destroyed as the CRT's DllMain will be called with DLL_THREAD_ATTACH and DLL_THREAD_DETACH when calling CreateThread() and ExitThread() or returning, respectively.

    The DllMain code for the CRT can be found in the install directory for VS under VC\crt\src\crtlib.c.

    0 讨论(0)
  • 2020-11-22 17:41

    CreateThread() is a raw Win32 API call for creating another thread of control at the kernel level.

    _beginthread() & _beginthreadex() are C runtime library calls that call CreateThread() behind the scenes. Once CreateThread() has returned, _beginthread/ex() takes care of additional bookkeeping to make the C runtime library usable & consistent in the new thread.

    In C++ you should almost certainly use _beginthreadex() unless you won't be linking to the C runtime library at all (aka MSVCRT*.dll/.lib).

    0 讨论(0)
提交回复
热议问题