Windows 스레딩 : _beginthread vs _beginthreadex vs CreateThread C ++


133

스레드, 시작하는 더 좋은 방법이 무엇인가 _beginthread, _beginthreadx또는 CreateThread?

나는의 장점 / 단점이 무엇인지를 결정하기 위해 노력하고있어 _beginthread, _beginthreadex하고 CreateThread. 이 모든 함수는 스레드 핸들을 새로 생성 된 스레드로 반환합니다 .CreateThread는 오류가 발생할 때 약간의 추가 정보를 제공한다는 것을 알고 있습니다 (호출하여 확인할 수 있음 GetLastError) ...하지만 내가 할 때 고려해야 할 사항은 무엇입니까? 이 기능을 사용하고 있습니까?

Windows 응용 프로그램으로 작업 중이므로 크로스 플랫폼 호환성은 이미 의문의 여지가 없습니다.

나는 msdn 문서를 살펴 보았는데, 예를 들어 누군가 왜 CreateThread 대신 _beginthread를 사용하기로 결정했는지 또는 그 반대인지 이해할 수 없습니다.

건배!

업데이트 : 좋아, 모든 정보에 감사드립니다. WaitForSingleObject()사용하면 호출 할 수없는 두 곳에서 읽었 _beginthread()지만 _endthread()스레드를 호출 하면 작동하지 않아야합니까? 거래는 무엇입니까?


2
다음은 Eli Bendersky 웹 사이트의 링크에서 찾은 C / C ++ 프로그래머위해 _beginthreadex () 가 수행 하는 작업에 대한 분석입니다 . 이것은 CreateThread () 사용 여부에 관한 Q & A에서 온 것입니다. microsoft.com/msj/0799/win32/win320799.aspx
Richard Chambers

답변:


96

CreateThread() 커널 수준에서 다른 제어 스레드를 작성하기위한 원시 Win32 API 호출입니다.

_beginthread()& 뒤에서 _beginthreadex()호출하는 C 런타임 라이브러리 호출입니다 CreateThread(). 일단 CreateThread()반환 되면 _beginthread/ex()추가 런타임을 처리하여 C 런타임 라이브러리를 새 스레드에서 사용 가능하고 일관성있게 만듭니다.

C ++에서는 C _beginthreadex()런타임 라이브러리 (MSVCRT * .dll / .lib)에 전혀 연결하지 않는 한 거의 확실하게 사용해야 합니다.


39
더 이상 예전처럼 사실이 아닙니다. CRT는 signal () 함수를 제외하고 CreateThread ()로 작성된 스레드에서 올바르게 작동합니다. CRT를 사용하는 CreateThread ()로 작성된 각 스레드에 대해 작은 메모리 누수 (~ 80 바이트)가 발생하지만 올바르게 작동합니다. 자세한 내용은 support.microsoft.com/default.aspx/kb/104641을
John Dibling

1
@ 존 : 사실이 버그는 MSVC ++ 6.0
bobobobo

5
@bobobobo : 좋은 질문입니다. 나는 MS가 원래 _begin루틴을 내부 호출로 의도하고 CreateThread모든 사람이 호출하는 API 함수라고 생각했다. 또 다른 잠재적 인 설명은 MS가 표준을 무시하고 사물 이름을 짓는 것에 대해 매우 나쁜 결정을 내리는 길고 영광스러운 역사를 가지고 있다는 것입니다.
John Dibling

15
_begin기능은 밑줄로 시작 하기 때문에 마이크로 소프트가 더 밀접하게 표준을 따라하기 시작했다. C 런타임에서 밑줄이있는 이름은 구현 용으로 예약되어 있으며 구현시 최종 사용자 용으로 문서화 할 수 있습니다. beginthreadex()사용자가 사용할 수있는 이름입니다. C 런타임에서이를 사용하는 경우 사용자가 사용할 것으로 기대할 수있는 합법적 인 권한을 가지고있는 최종 사용자 기호와 충돌 할 수 있습니다. Win32 API는 C 런타임의 일부가 아니며 사용자의 네임 스페이스를 사용합니다.
Michael Burr

2
@Lothar : Win32 API 호출 과 CRT 호출 간에 차이 가 있으며 스레드에서 CRT를 호출 할 때는 항상로 작성해야합니다 . 그렇지 않으면 더 이상 메모리 누수가 없을 수 있습니다. 그러나 예를 들어을 호출 할 때 부동 소수점 환경이 올바르게 초기화되지는 않습니다 . 거기에 : "스레드를 사용하여 만든 경우 CreateThread가 브라운관을 호출의 CRT는 메모리 부족 조건에서 프로세스를 종료 할 수 있습니다." CreateThread_beginthread/ex_beginthread/exCreateThread
IInspectable

37

_beginthread()와 사이에는 몇 가지 차이점이 있습니다 _beginthreadex(). (매개 변수와 동작 방식)에서 _beginthreadex()더 비슷하게 작동하도록 만들어졌습니다 CreateThread().

Drew Hall이 언급 했듯이 C / C ++ 런타임을 사용 하는 경우 런타임이 자체 스레드 초기화 (스레드 로컬 스토리지 설정 등)를 수행 할 수 있도록 대신 _beginthread()/ 를 사용해야합니다 ._beginthreadex()CreateThread()

실제로 이것은 CreateThread()코드에서 직접 사용하지 않아야 함을 의미합니다 .

차이점에 대한 MSDN 문서 _beginthread()/ _beginthreadex()자세한 내용은 매우 중요합니다. 더 중요한 것 중 하나 _beginthread()는 스레드가 종료 될 때 생성 된 스레드의 스레드 핸들 이 CRT에 의해 자동으로 닫히기 때문에 "_beginthread에 의해 생성 된 스레드가 종료되면 _beginthread의 호출자에게 리턴 된 핸들이 유효하지 않거나 다른 스레드를 가리킬 수 있습니다. "

_beginthreadex()CRT 소스에 대한 의견은 다음과 같습니다 .

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).

2013 년 1 월 업데이트 :

VS 2012의 CRT에는 다음과 같은 추가 초기화 비트가 있습니다 _beginthreadex(). 프로세스가 "패키지 된 앱"인 경우 (유용한 것이 반환 된 경우 GetCurrentPackageId()) 런타임은 새로 작성된 스레드에서 MTA를 초기화합니다.


3
있습니다 CreateThread ()가 보증 적절한 시간,하지만 솔직히 당신이 정말로 그것을 할 길의 외출해야합니다. 우리는 이식성이 전혀 없으며 독점적으로 WIN32 API DLL 또는 앱을 작성하고 있습니다. C 런타임 호출을 포함하지 않습니다. STL 사용도 WIN32 메모리 관리 기능을 사용하려면 사용자 지정 할당자를 제공해야한다는 점에서 제한됩니다. Developer Studio를 사용하여이 작업을 수행하는 설정은 그 자체로 수행되지만 가능한 가장 작은 설치 공간을 가진 유일한 Win32 라이브러리의 경우에는 수행 할 수 있습니다. 그러나 네, 거의 모든 사람들에게 피의 가능성이 거의 없습니다.
WhozCraig

1
@WhozCraig : CRT를 생략 할 때 더 심각한 제한이 있습니다. 가장 눈에 띄는 것은 다음과 같습니다. 64 비트 정수 지원, 부동 소수점 지원 없음 및 가장 대폭적인 예외 처리 없음. 이것은 실제로 예외 처리가 전혀 없다는 것을 의미 합니다 . SEH 예외도 아닙니다. 이것은 특히 보충하기가 어렵고 CreateThread옳은 일 이라고 부를 가능성 은 줄어 듭니다.
IInspectable

@MichaelBurr : VC ++ 2015에 대한 답변업데이트 할 수 있습니다 .
user541686

@Mehrdad : 특별히 언급 할 가치가있는 변경 사항은 무엇입니까?
IInspectable

DisableThreadLibraryCalls가 CreateThread로 작성된 스레드에는 영향을 미치지 않지만 _beginthread 또는 _beginthreadex로 작성된 스레드는 비활성화합니다.
09 초에

23

일반적으로 올바른 작업은 전화 _beginthread()/_endthread()(또는 ex()변형) 를 호출하는 것입니다 . 당신이 .DLL로 CRT를 사용하는 경우 그러나 CRT 상태가 제대로 초기화와 CRT의 파괴 될 것이다는 DllMain호출 될 것입니다 DLL_THREAD_ATTACHDLL_THREAD_DETACH호출 할 때 CreateThread()ExitThread()또는 각각 반환.

DllMainCRT 의 코드는 VS의 설치 디렉토리 (VC \ crt \ src \ crtlib.c)에 있습니다.


좋은 출발점. 약간의 디버깅으로 __CRTDLL_INIT가 정적으로 링크 된 CRT에서도 호출됨을 알 수 있습니다. init가 _LdrpCallInitRoutine @ 16 ()에서 호출됩니다. 정확히 어떤 메커니즘인지 확실하지 않습니다. 이것은 최근 CRT에서 신호 처리를 제외하고 모든 초기화 / 비 초기화가 올바르게 수행됨을 의미하며, 이는 CreateThread가 아닌 beginthread에서 호출 된 _threadstartex 도우미 함수에서 여전히 수행됩니다. 아마도 당신은 이것을 대답에 추가 할 수 있으며 현상금을 수여 할 것입니까?
Suma

이것이 가장 도움이되는 것처럼 현상금이 수여되었습니다. 여전히 대답은 아마도 가치가 있습니다. 당신이 그것을 할 수 없다면, 나는 며칠 안에 그것을 다시 방문 할 수 있습니다.
Suma

1
@MSN : CreateThread는 DLL에서 여전히 나쁘다는 점에 유의하십시오. 정적 CRT를 다시 연결 하고 DisableThreadLibraryCalls를 호출하여 DLL_THREAD_DETACH에 대한 호출을 비활성화하면 그런 다음 메모리 누수가 발생합니다. 이것은 내 KB 문서에서 여기에 설명되어 있습니다 : support.microsoft.com/kb/555563/en-us
요헨 Kalmbach을

17

이것은 핵심 코드입니다 _beginthreadex(참조 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;
    }

나머지는 _beginthreadexCRT에 대한 스레드 별 데이터 구조를 초기화합니다.

_beginthread*스레드의 CRT 호출이 올바르게 작동한다는 장점 이 있습니다.


12

C 런타임 라이브러리가 스레드의 자체 초기화를 수행하도록 _beginthread또는 _beginthreadex허용 해야합니다 . C / C ++ 프로그래머 만이 자신의 개발 환경을 사용하는 규칙을 따라야하므로이를 알아야합니다.

당신이 사용한다면 RTL이 당신을 위해 할 것이므로 _beginthread전화를 걸 필요가 없습니다 CloseHandle. 당신이 사용하는 경우 핸들을 기다릴 수없는 이유 _beginthread입니다. 또한 _beginthread시작 스레드가 유효하지 않은 스레드 핸들을 방금 시작한 스레드에 유지하면서 스레드 기능이 즉시 (빠르게) 종료되면 혼란을 초래합니다.

_beginthreadex핸들은 대기에 사용될 수 있지만에 대한 명시적인 호출이 필요합니다 CloseHandle. 이것은 대기와 함께 사용하기에 안전한 부분입니다. 완전히 무례하게 만드는 다른 문제는 항상 스레드를 일시 중단하는 것입니다. 성공, 레코드 핸들 등을 점검하십시오. 이력서 스레드. 이것은 시작 스레드가 핸들을 기록하기 전에 스레드가 종료되는 것을 방지하기 위해 필요합니다.

가장 좋은 방법은을 사용하고 _beginthreadex, 일시 중지를 시작한 다음 기록 핸들 후 재개하고, 핸들 대기가 정상 CloseHandle입니다.


8

CreateThread()코드에서 CRT 함수를 사용할 때 메모리 누수가 발생했습니다. _beginthreadex()와 동일한 매개 변수를 CreateThread()가지며보다 다재다능합니다 _beginthread(). 을 사용하는 것이 좋습니다 _beginthreadex().


2
1999 년 기사, 수정되었을 수 있음
bobobobo

1
2005 년 이 기사 는 여전히 문제가 있음을 확인합니다.
Jaywalker

2
예, MSVC ++ 6.0 서비스 팩 5 및 이전 버전에만 적용됩니다. ( "적용 대상"확장 가능 드롭 다운 참조). VC7 이상을 사용하는 경우 오늘날에는 문제가되지 않습니다.
bobobobo 2016 년

1
정적 CRT를 다시 연결하면 여전히 문제가됩니다! 또한 정적으로 링크 된 DLL에서 DisableThreadLibraryCalls를 호출하면 여전히 문제가됩니다. 내 KB 기사 참조 : support.microsoft.com/kb/555563/en-us
Jochen Kalmbach

2
정보를 잘못 표시 한 경우 : 메모리 누출 CreateThread되지 않습니다 . 제대로 초기화되지 않은 스레드에서 호출되는 것은 오히려 CRT입니다.
IInspectable

6

업데이트 된 질문과 관련하여 : "또한 WaitForSingleObject()사용할 경우 호출 할 수없는 몇 곳에서 읽었 _beginthread()지만 _endthread()스레드를 호출 하면 작동하지 않아야합니까?"

일반적으로 스레드 핸들 WaitForSingleObject()(또는 객체 핸들을 기다리는 다른 API)에 스레드 핸들을 전달 하여 스레드가 완료 될 때까지 차단할 수 있습니다. 그러나에 의해 작성된 스레드 핸들 은 호출 _beginthread()될 때 닫힙니다 _endthread()(스레드 프로 시저가 리턴 될 때 런타임에 명시 적으로 수행되거나 내재적으로 수행 될 수 있음).

이 문제는 다음 문서에 나와 있습니다 WaitForSingleObject().

대기가 여전히 보류중인 동안이 핸들이 닫히면 함수의 동작이 정의되지 않습니다.


5

함수 시그니처를 보면 CreateThread거의 동일합니다 _beginthreadex.

_beginthread,_beginthreadx vsCreateThread

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 
);

의 발언 여기가 말을 _beginthread하거나 사용할 수 있습니다 __cdecl또는 __clrcall시작 지점으로 호출 규칙 및 _beginthreadex중 하나를 사용할 수 있습니다 __stdcall또는 __clrcall시작 지점.

메모리 누수에 대한 사람들의 의견 CreateThread은 10 년이 넘었으므로 무시해야 한다고 생각합니다 .

흥미롭게도 두 _beginthread*기능은 실제로 내 컴퓨터 CreateThread에서 후드를 호출 C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\src합니다.

// 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;
}

2
당신이 CreateThread를 호출하고 (십년 오래된하지, 확실히 그 스레드에서 CRT 통화에서 혼합하지해야하는 이유에 대한 댓글 확실히 무시해서는 안됩니다) : "스레드가 CreateThread가 CRT를 호출하여 만든 경우 CRT가의 프로세스를 종료 할 수 있습니다 메모리 부족 조건 "
IInspectable

3

beginthreadex당신 과 친구들에게 쓰레드 HANDLE를 제공합니다 WaitForSingleObject. beginthread하지 않습니다. CloseHandle()끝났을 때 잊지 마세요 . 진정한 대답은 boost::thread곧 C ++ 09의 스레드 클래스를 사용하는 것입니다.


msdn 설명에 따르면 "성공하면 이러한 각 함수가 새로 만든 스레드에 대한 핸들을 반환합니다."라고 말합니다. _beginthread () 및 _beginthreadex ()를 참조하십시오 ...
Kiril

@Kiril :하지만 문서는 _beginthread가 핸들을 닫았다는 것을 말해줍니다. 즉, 스레드가 빠르게 종료되면 핸들을 닫을 수 없습니다.
Roger Lipscombe

2

에 비해 다음 _beginthread과 같은 이점 _beginthreadex이 있습니다.

  1. 보안 속성을 지정하십시오.
  2. 일시 중단 상태에서 스레드를 시작합니다.
  3. 와 함께 사용할 수있는 스레드 ID를 얻을 수 있습니다 OpenThread.
  4. 호출이 성공하면 리턴 된 스레드 핸들이 유효합니다. 로 핸들을 닫아야합니다 CloseHandle.
  5. 리턴 된 스레드 핸들은 동기화 API와 함께 사용할 수 있습니다.

_beginthreadex밀접는 유사 CreateThread하지만, 전자는 CRT 구현과 후자의 윈도우 API 호출입니다. CreateThread 설명서 에는 다음 권장 사항이 포함되어 있습니다.

C 런타임 라이브러리 (CRT)를 호출 실행에서의 스레드는 사용해야 _beginthreadex_endthreadex보다는 스레드 관리를위한 기능을 CreateThread하고 ExitThread, 이를 위해서는 멀티 스레드 버전의 CRT를 사용해야합니다. 스레드를 사용하여 작성된 스레드 CreateThread가 CRT 를 호출하면 CRT는 메모리 부족 조건에서 프로세스를 종료 할 수 있습니다.


API 사양에 따르면 글 머리 기호 3-5는 고유하지 않습니다 _beginthreadex. uintptr_t두 함수에서 모두로 수익을 캐스트 할 수 있습니다 HANDLE.
Andon M. Coleman

예, 당신은 이론에 맞습니다. 실제로 차이점은 _beginthread종료시 핸들 을 닫는 것입니다. 따라서 핸들을 동기화하고 복제하는 다른 방법을 사용하지 않는 한 동기화 API와 함께 핸들을 안정적으로 사용하거나 스레드 ID를 가져올 수 없습니다. 그러나 _beginthreadex당신을 위해 그것을하고 있습니다.
Vishal

2

CreateThread()CRT가 잘못 초기화 / 정리 되었기 때문에 한 번은 아니오였습니다. 그러나 이것은 이제 역사입니다. 이제 CreateThread()CRT를 중단하지 않고도 VS2010 및 아마도 몇 가지 버전을 다시 사용할 수 있습니다 .

여기 공식 MS 확인서가 있습니다. 한 가지 예외가 있습니다.

실제로, 스레드로 사용해서는 안되는 유일한 함수 CreateThread()signal()함수입니다.

그러나 일관성 관점에서 개인적으로을 계속 사용하는 것을 선호합니다 _beginthreadex().


이것이 사실이라고 생각하지만 MS Documentation에 연결하거나 CRT _beginthreadex / _endthreadex 소스를 분석하여 권위있는 증거를 제공 할 수 있습니까?
Suma

@Suma, 난 당신이 귀하의 의견을 입력하는 동안 MS 링크를 추가했다고 생각합니다 ;-)
Serge Wautier

연결하려는 문서가 다음과 같은 내용을 확인하지 못하는 것 같습니다. "CRT 함수의 호출에 따라 스레드가 종료 될 때 작은 메모리 누수가있을 수 있습니다." 이것은 더 이상 크고 일반적인 no-no가 아니라 스레드를 자주 만들고 그 기능을 사용하는 경우 여전히 no-no라는 것을 의미합니다. 그러나이 문서는 2005 년에 발간 된 문서이므로 최근 문제를 다룰 수 없습니다.
Suma

1
흠 ... 유스 케이스, 메모리 누수를 떠나는 기능에 따라 다르지만 크기에 관계없이 아니오를 고려할 것입니다 ... 특히 비 누출 대안이있는 경우!
alk

"CRT를 깨지 않고도 CreateThread ()를 호출 할 수 있습니다." -불행히도, 이것은 사실이 아니며 결코 없었습니다. 에서 CreateThread : 스레드가 CreateThread가 CRT를 호출하여 만든 경우 "C 런타임 라이브러리 (CRT)를 호출하는 실행 파일에 스레드가 스레드 관리를위한 _beginthreadex 및 _endthreadex 함수를 사용한다 [...]의 CRT는을 해지 할 수 있습니다 메모리 부족 조건에서 처리합니다. "
IInspectable

2

CreateThread()언어 중립적 인 Windows API 호출입니다. 그것은 단지 OS 객체-스레드를 생성 하고이 스레드에 HANDLE을 반환합니다. 모든 Windows 응용 프로그램은이 호출을 사용하여 스레드를 만듭니다. 모든 언어는 명백한 이유로 직접 API 호출을 피합니다. 1. 코드가 OS에 고유하지 않기를 원합니다. 2. API와 같이 호출하기 전에 일부 하우스 키핑을 수행해야합니다. 매개 변수 및 결과 변환, 임시 스토리지 할당 등

_beginthreadex()C 관련 래퍼 CreateThread()입니다. 스레드 별 스토리지를 할당하여 다중 스레드 환경에서 원래 단일 스레드 C f-ns 작업을 수행 할 수 있습니다.

CRT를 사용하지 않으면에 직접 전화를 걸 수 없습니다 CreateThread(). CRT를 사용하는 경우 _beginthreadex()VC2005 이전에 일부 CRT 문자열 f-ns가 제대로 작동하지 않을 수 있습니다.


1

CreateThread()바로 시스템 호출입니다. 에 그것은 구현있어 Kernel32.dll, 이는 대부분의 아마, 당신의 응용 프로그램이 이미 다른 이유에 대해 연결됩니다. 항상 최신 Windows 시스템에서 사용할 수 있습니다.

_beginthread()그리고 _beginthreadex()는 Microsoft C 런타임에서 래퍼 기능 (입니다 msvcrt.dll). 두 통화의 차이점은 설명서에 나와 있습니다. 따라서 Microsoft C 런타임이 사용 가능하거나 애플리케이션이 정적으로 링크 된 경우에 사용 가능합니다. 순수한 Windows API로 코딩하지 않는 한 (개인적으로하는 것처럼) 라이브러리와도 연결되어있을 수 있습니다.

귀하의 질문은 일관되고 실제로 반복되는 질문입니다. 많은 API와 마찬가지로 Windows API에는 중복되고 모호한 기능이 있습니다. 무엇보다도 문서는 문제를 명확하게 설명하지 않습니다. 나는 _beginthread()함수 계열이와 같은 다른 표준 C 기능과 더 잘 통합되도록 만들어 졌다고 가정합니다 errno. _beginthread()따라서 C 런타임과 더 잘 통합됩니다.

당신이 사용하는 이유가 없다면 그럼에도 불구하고, _beginthread()또는 _beginthreadex(), 당신은 사용해야 CreateThread()당신이 당신의 최종 실행 한 적은 라이브러리 의존성을 얻을 수 있습니다 주로하기 때문에을 (그리고 MS CRT이가하는 약간의 문제). 이 효과는 무시해도 좋지만 호출 주위에 줄 바꿈 코드는 없습니다. 다시 말해서, 나는 고집해야 할 주된 이유 CreateThread()는 사용 _beginthreadex()하기에 좋은 이유가 없기 때문이라고 믿는다 . 기능은 정확히 또는 거의 동일합니다.

사용에 대한 하나의 좋은 이유가 _beginthread() 경우 C ++ 객체가 제대로 풀리고 / 파괴 될 것이라고 (이 거짓으로 보인다) _endthread()라고했다.


더 모호한 함수 호출이 없습니다 모두에서이 . CreateThread스레드를 작성하기위한 Windows API 호출입니다. CRT를 사용하는 경우 (C 또는 C ++로 프로그래밍하기 때문에) CRT _beginthread[ex]호출 ( CreateThread필요한 CRT 초기화 수행 외에 호출)을 사용하여 스레드를 작성해야합니다 . _beginthread변이와 변이 의 가장 중요한 차이점 : 전자는 기본 스레드 핸들의 소유권을 유지하고 후자는 소유권을 호출자에게 전달합니다.
IInspectable

Nitpick : C 런타임 DLL msvcrt.dll아닙니다 ! blogs.msdn.microsoft.com/oldnewthing/20140411-00/?p=1273
Govind Parmar

0

다른 답변은 Win32 API 함수를 래핑하는 C 런타임 함수 호출의 의미를 논의하지 못합니다. DLL 로더 잠금 동작을 고려할 때 중요합니다.

_beginthread{ex}다른 답변에서 설명하는 것처럼 특수한 C 런타임 스레드 / 섬유 메모리 관리 여부에 관계없이 프로세스가 아직로드하지 않은 DLL (C 런타임에 동적 링크를 가정)로 구현됩니다.

에서 전화 _beginthread*하는 것은 안전하지 않습니다 DllMain. Windows "AppInit_DLLs"기능을 사용하여로드 된 DLL을 작성하여이를 테스트했습니다. _beginthreadex (...)대신에 호출 CreateThread (...)하면 DllMain특정 초기화 작업을 수행하기 위해 로더 잠금이 해제되기를 기다리는 진입 점 교착 상태 로 부팅 중 Windows의 많은 부분이 작동하지 않습니다 .

우연히도 이것이 kernel32.dll 이 C 런타임에서도 겹치는 문자열 함수를 많이 가지고있는 이유 이기도 DllMain합니다.


0

Jeffrey Richter의 Windows 응용 프로그램 디버깅 책을 읽으면 거의 모든 경우에 전화하는 _beginthreadex대신 전화해야한다고 설명합니다 CreateThread. _beginthread그냥 간단한 래퍼 _beginthreadex입니다.

_beginthreadexCreateThreadAPI가 수행하지 않는 특정 CRT (C 런타임) 내부를 초기화 합니다.

CRT 함수 호출을 사용하는 CreateThread대신 API 를 사용하면 _begingthreadex예기치 않은 문제가 발생할 수 있습니다.

이 오래된 Microsoft Journal From Richter를 확인하십시오.


-2

둘 사이에는 더 이상 차이가 없습니다.

메모리 누수 등에 대한 모든 의견은 매우 오래된 <VS2005 버전을 기반으로합니다. 몇 년 전에 스트레스 테스트를 해본 결과이 신화를 깨뜨릴 수 있습니다. Microsoft조차도 예제에서 스타일을 혼합하지만 거의 _beginthread를 사용하지 않습니다.



"CRT의 멀티 스레드 버전의 사용이 필요하다"는 내용에 기초하여 더 이상 그리고 수년 동안 멀티 스레딩 된 crt 버전이 없기 때문에 이것은 문서 쓰레기라고 가정합니다.
Lothar

"어떤 멀티 스레드 CRT 버전은 더 이상 없다" - MSDN의 주장이 "[t] 그가 CRT 더 이상 사용할 수 단일 스레드 없습니다." 둘 다 옳을 수는 없습니다. 여기에서도 MSDN을 사용하겠습니다.
IInspectable

물론 오타였습니다. 단일 스레드가 사라지고 멀티 스레드가 표준이되었으며 사라지는 것은 스레드 사용 여부를 구별하는 것입니다.
Lothar

정말 이상해 이제 의심 할 여지없이 맞습니다 성명을 사용하는 ( "는 CRT의 멀티 스레드 버전의 사용이 필요합니다" 이 문장뿐만 아니라 문서의 나머지 둘은 매우 가능성이 잘못이라고 주장과를)? 확실하게 들리지 않습니다.
IInspectable
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.