Copyright © Microsoft Corporation. This document is an archived reproduction of a version originally published by Microsoft. It may have slight formatting modifications for consistency and to improve readability.
Figure 1   Visual C++ Runtime Libraries

Library Name
Description
LIBC.LIB
Statically linked library for single-threaded applications (this is the default library chosen when you create a new project).
LIBCD.LIB
Statically linked debug version of the library for single-threaded applications.
LIBCMT.LIB
Statically linked release version of the library for multithreaded applications.
LIBCMTD.LIB
Statically linked debug version of the library for multithreaded applications.
MSVCRT.LIB
Import library for dynamically linking the release version of the MSVCRT.DLL library. The library supports both single-threaded and multithreaded applications.
MSVCRTD.LIB
Import library for dynamically linking the debug version of the MSVCRT.DLL library. The library supports both single-threaded and multithreaded applications.


Figure 3   _beginthreadex Pseudocode


 unsigned long __cdecl _beginthreadex (
     void *psa,
     unsigned cbStack,
     unsigned (__stdcall * pfnStartAddr) (void *),
     void * pvParam,
     unsigned fdwCreate,
     unsigned *pdwThreadID) {
 
     _ptiddata ptd;         // Pointer to thread's data block
     unsigned long thdl;    // Thread's handle
 
     // Allocate data block for the new thread
     if ((ptd = calloccrt(1, sizeof(struct tiddata))) == NULL)
         goto errorreturn;
 
     // Initialize the data block
     initptd(ptd);
 
     // Save the desired thread function and the parameter
     // we want it to get in the data block
     ptd->_initaddr = (void *) pfnStartAddr;
     ptd->_initarg = pvParam;
 
     // Create the new thread
     thdl = (unsigned long) CreateThread(psa, cbStack,
         _threadstartex, (PVOID) ptd, fdwCreate, pdwThreadID);
     if (thdl == NULL) {
         // Thread couldn't be created, cleanup and return failure
         goto error_return;
     }
 
     // Create created OK, return the handle
     return(thdl);
 
 error_return:
     // Error: data block or thread couldn't be created
     _free_crt(ptd);
     return((unsigned long)0L);
 }

Figure 4   The tiddata Structure


 struct _tiddata {
     unsigned long   _tid;            /* thread ID */
 
 
     unsigned long   _thandle;        /* thread handle */
     int             _terrno;         /* errno value */
     unsigned long   _tdoserrno;      /* _doserrno value */
     unsigned int    _fpds;           /* Floating Point data segment */
     unsigned long   _holdrand;       /* rand() seed value */
     char *          _token;          /* ptr to strtok() token */
 #ifdef _WIN32
     wchar_t *       _wtoken;         /* ptr to wcstok() token */
 #endif  /* _WIN32 */
     unsigned char * _mtoken;         /* ptr to _mbstok() token */
 
         /* following pointers get malloc'd at runtime */
     char *          _errmsg;         /* ptr to strerror()/_strerror() buff */
     char *          _namebuf0;       /* ptr to tmpnam() buffer */
 #ifdef _WIN32
     wchar_t *       _wnamebuf0;      /* ptr to _wtmpnam() buffer */
 #endif  /* _WIN32 */
     char *          _namebuf1;       /* ptr to tmpfile() buffer */
 #ifdef _WIN32
     wchar_t *       _wnamebuf1;      /* ptr to _wtmpfile() buffer */
 #endif  /* _WIN32 */
     char *          _asctimebuf;     /* ptr to asctime() buffer */
 #ifdef _WIN32
     wchar_t *       _wasctimebuf;    /* ptr to _wasctime() buffer */
 #endif  /* _WIN32 */
     void *          _gmtimebuf;      /* ptr to gmtime() structure */
     char *          _cvtbuf;         /* ptr to ecvt()/fcvt buffer */
 
     /* following fields are needed by _beginthread code */
     void *          _initaddr;       /* initial user thread address */
     void *          _initarg;        /* initial user thread argument */
 
     /* following three fields are needed to support signal handling and
      * runtime errors */
     void *          _pxcptacttab;    /* ptr to exception-action table */
     void *          _tpxcptinfoptrs; /* ptr to exception info pointers */
     int             _tfpecode;       /* float point exception code */
 
     /* following field is needed by NLG routines */
     unsigned long   _NLG_dwCode;
 
     /*
      * Per-Thread data needed by C++ Exception Handling
      */
     void *          _terminate;     /* terminate() routine */
     void *          _unexpected;    /* unexpected() routine */
     void *          _translator;    /* S.E. translator */
     void *          _curexception;  /* current exception */
     void *          _curcontext;    /* current exception context */
 #if defined (_M_MRX000)
     void *          _pFrameInfoChain;
     void *          _pUnwindContext;
     void *          _pExitContext;
     int             _MipsPtdDelta;
     int             _MipsPtdEpsilon;
 #elif defined (_M_PPC)
     void *          _pExitContext;
     void *          _pUnwindContext;
     void *          _pFrameInfoChain;
     int             _FrameInfo[6];
 #endif  /* defined (_M_PPC) */
     };
 
 typedef struct _tiddata * _ptiddata;

Figure 5   _threadstartex Pseudocode


 static unsigned long WINAPI _threadstartex (void* ptd) {
    // Note: ptd is the address of this thread's tiddata block

    // Associate the tiddata block with this thread
    TlsSetValue(__tlsindex, ptd);

    // Save this thread ID in the tiddata block
    ((_ptiddata) ptd)->_tid = GetCurrentThreadId();

    // Initialize floating-point support (code not shown) 

    // Wrap desired thread function in SEH frame to 
    // handle runtime errors and signal support
    __try {
        // Call desired thread function passing it the desired parameter
        // Pass threads exit code value to _endthreadex
        _endthreadex(
          ( (unsigned (WINAPI *)(void *))(((_ptiddata)ptd)->_initaddr) )
              ( ((_ptiddata)ptd)->_initarg ) ) ;
    }
    __except(_XcptFilter(GetExceptionCode(), GetExceptionInformation()){
        // The C-Runtime's exception handler deals with runtime errors
        // and signal support, we should never get it here.
        _exit(GetExceptionCode());
    }

    // We never get here, the thread dies in this function
    return(0L);
}