Windows threading: _beginthread vs _beginthreadex vs CreateThread C++

后端 未结 17 1268
臣服心动
臣服心动 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:51

    The other answers fail to discuss the implications of calling a C run-time function that wraps a Win32 API function. This is important when considering DLL loader locking behavior.

    Whether or not _beginthread{ex} does any special C Runtime thread/fiber memory management as the other answers discuss, it is implemented in (assuming dynamic linking to the C run-time) a DLL that processes may not have loaded yet.

    It is not safe to call _beginthread* from DllMain. I have tested this by writing a DLL loaded using the Windows "AppInit_DLLs" feature. Calling _beginthreadex (...) instead of CreateThread (...) causes a LOT of important parts of Windows to stop functioning during bootup as the DllMain entry-point deadlocks waiting for the loader lock to be released in order to perform certain initialization tasks.

    Incidentally, this is also why kernel32.dll has a lot of overlapping string functions that the C run-time also does -- use those from DllMain to avoid the same sort of situation.

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

    This is the code at the core of _beginthreadex (see crt\src\threadex.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;
        }
    

    The rest of _beginthreadex initializes per-thread data structure for CRT.

    The advantage of using _beginthread* is that your CRT calls from thread will work correctly.

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

    CreateThread() used to have memory leaks when you use any CRT functions in your code. _beginthreadex() has same parameters as CreateThread() and it's more versatile than _beginthread(). So I recommend you use _beginthreadex().

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

    If you read the book Debugging Windows Application From Jeffrey Richter in it he explains that almost in all instances you must call _beginthreadex instead of calling CreateThread. _beginthread is just a simplified wrapper around _beginthreadex.

    _beginthreadex initializes certain CRT (C RunTime) internals that the CreateThread API would not do.

    A consequence if you use the CreateThread API instead of using _begingthreadex calls to CRT functions might unexpected cause issues.

    Check out this old Microsoft Journal From Richter.

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

    There are several differences between _beginthread() and _beginthreadex(). _beginthreadex() was made to act more like CreateThread() (in both parameters and how it behaves).

    As Drew Hall mentions, if you're using the C/C++ runtime, you must use _beginthread()/_beginthreadex() instead of CreateThread() so that the runtime has a chance to perform it's own thread initialization (setting up thread local storage, etc.).

    In practice, this means that CreateThread() should pretty much never be used directly by your code.

    The MSDN documents for _beginthread()/_beginthreadex() have quite a bit of detail on the differences - one of the more important is that since the thread handle for a thread created by _beginthread() gets closed automatically by the CRT when the thread exits, "if the thread generated by _beginthread exits quickly, the handle returned to the caller of _beginthread might be invalid or, worse, point to another thread".

    Here is what the comments for _beginthreadex() in the CRT source have to say:

    Differences between _beginthread/_endthread and the "ex" versions:
    
    1)  _beginthreadex takes the 3 extra parameters to CreateThread
      which are lacking in _beginthread():
        A) security descriptor for the new thread
        B) initial thread state (running/asleep)
        C) pointer to return ID of newly created thread
    
    2)  The routine passed to _beginthread() must be __cdecl and has
      no return code, but the routine passed to _beginthreadex()
      must be __stdcall and returns a thread exit code.  _endthread
      likewise takes no parameter and calls ExitThread() with a
      parameter of zero, but _endthreadex() takes a parameter as
      thread exit code.
    
    3)  _endthread implicitly closes the handle to the thread, but
      _endthreadex does not!
    
    4)  _beginthread returns -1 for failure, _beginthreadex returns
      0 for failure (just like CreateThread).
    

    Update Jan 2013:

    The CRT for VS 2012 has an additional bit of initialization performed in _beginthreadex(): if the process is a "packaged app" (if something useful is returned from GetCurrentPackageId()) the runtime will initialize the MTA on the newly created thread.

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