programing

c

coolbiz 2022. 8. 27. 23:53
반응형

Windows 스레드화: _beginthread vs _beginthreadx vs CreateThread C++

하는 더 _beginthread,_beginthreadx ★★★★★★★★★★★★★★★★★」CreateThread

장점이 어떤 _beginthread,_beginthreadex ★★★★★★★★★★★★★★★★★」CreateThread 새로 .Create 했을 때 약간의 한다는 것을 알고 있습니다 Thread는 에러 발생 시 콜을 통해 할 수 ).Create Thread는 오류가 발생했을 때 약간의 추가 정보를 제공한다는 것을 이미 알고 있습니다(콜을 통해 확인할 수 있습니다).GetLastError하지만 이 기능을 사용할 때 고려해야 할 점은 무엇입니까?

Windows 어플리케이션으로 작업하고 있기 때문에 크로스 플랫폼 호환성은 이미 문제 없습니다.

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

건배!

는 데 든사니다 update든 update 、 、 、 、 든 、 든 、 든 、 든 update update 。이데올로기 때문에WaitForSingleObject()내가 사용한다면_beginthread(), ""로 _endthread()게게효 과과 ??? ???기선무 무???

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

_beginthread()&_beginthreadex()를 하는 C CreateThread()원스 원스 원스CreateThread() 돌아왔습니다._beginthread/ex()는 새로운 스레드에서 C 런타임 라이브러리를 사용할 수 있고 일관된 상태로 만들기 위해 추가 부기를 처리합니다.

확실히 C++로, C++로, C+로, C+로, C+로, C+로, C+로, C+로, C+로, C+로, C+로, C+로, C+로, C+로, C+로, C+로, C+로, C+로, C+로,_beginthreadex()C는 MSVCRT*.dll/.lib)입니다.

이 옳습니다._beginthread()/_endthread() ()ex() 초기화되어 CRTdll로 파기됩니다.DllMain.DLL_THREAD_ATTACH ★★★★★★★★★★★★★★★★★」DLL_THREAD_DETACH를 호출할 때CreateThread() ★★★★★★★★★★★★★★★★★」ExitThread()또는 복귀할 수 있습니다.

DllMainCRT VS VC\crt\src\crtlib.에 c c c c c c

사이에는 몇 가지 차이점이 있다_beginthread() ★★★★★★★★★★★★★★★★★」_beginthreadex()_beginthreadex()더 비슷하게 행동하도록 만들어졌다.CreateThread()( 미 ( ( ( ( ( ( ( ( 。

드류 홀이 언급했듯이 C/C++ 런타임을 사용하는 경우_beginthread()/_beginthreadex()CreateThread()따라서 런타임에서 자체 스레드 초기화(스레드 로컬 스토리지 설정 등)를 수행할 수 있습니다.

은 '하다'라는 입니다.CreateThread()코드에서 직접 사용해서는 안 됩니다.

의 :_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를 초기화합니다.

하면 됩니다._beginthread ★★★★★★★★★★★★★★★★★」_beginthreadexC 런타임 라이브러리가 스레드의 자체 초기화를 수행할 수 있도록 합니다.C/C++로 하다.C/C++로 하다.그것은, 독자적인 개발 환경을 사용하는 룰이 필요하기 때문입니다.

「 」를 사용하고 _beginthread 전화할 는 없어요.CloseHandleRTL을 사용합니다. '', '손잡이', '손잡이', '손잡이'를 사용한 적이 수 ._beginthread . 。_beginthread만약 스레드 기능이 즉시 종료되면(실행하지 않으면) 혼란이 생깁니다.이것은, 기동한 스레드에 대해서, 무효인 스레드 핸들을 잡고 있는 채로 있기 때문입니다.

_beginthreadex할 수 ""에 대한 합니다.CloseHandle이것은 대기 상태에서 사용해도 안전한 이유 중 하나입니다.완전히 오류를 방지하기 위한 또 다른 문제는 항상 나사산을 매달아 시동하는 것입니다. 스레드」, 「핸들을 되지 않도록 위해 합니다.이는 시작 스레드가 핸들을 기록하기 전에 스레드가 종료되지 않도록 하기 위해 필요합니다.

는 ''를 사용하는 입니다._beginthreadex후, start suspended는 녹음 핸들, wait on handle, wait on handle.CloseHandle를 호출해야 합니다.

CreateThread() 코드 내에서 CRT 함수를 사용하면 메모리 누수가 발생합니다. _beginthreadex() has has has has has has has has has has has has has has has has 와 같은 파라미터를 CreateThread()_beginthread() 꼭 하시길 권해드립니다._beginthreadex().

CreateThread()는 스트레이트 시스템콜입니다에 실장되어 있습니다.Kernel32.dll아마 다른 이유로 어플리케이션이 이미 링크되어 있을 것입니다.신 windows Windows の스항사사사수수수 。

_beginthread() ★★★★★★★★★★★★★★★★★」_beginthreadex()는, CRuntime( 「 」 , Microsoft C Runtime の 「 」 )의입니다.msvcrt.dll되어 있습니다 2개의 콜의 차이는 매뉴얼에 기재되어 있습니다.따라서 Microsoft C Runtime을 사용할 수 있는 경우 또는 응용 프로그램이 이에 대해 정적으로 링크되어 있는 경우에 사용할 수 있습니다.순수한 Windows API로 코딩하지 않는 한 라이브러리와 링크할 수도 있습니다(제가 자주 하는 것처럼).

당신의 질문은 일관성이 있고 실제로 반복되는 것이다.많은 API와 마찬가지로 Windows API에는 중복되고 애매한 기능이 있습니다.무엇보다도 이 문서에는 문제가 명확하지 않습니다.제 생각엔_beginthread()기능 패밀리는 다른 표준 C 기능과의 더 나은 통합을 위해 만들어졌다. 예를 들어, 의 조작errno._beginthread()따라서 C 런타임과 더 잘 통합됩니다.

그럼에도 불구하고, 적절한 이유가 없는 한_beginthread()또는_beginthreadex(), 를 사용해 주세요.CreateThread()이는 주로 최종 실행 파일에서 라이브러리 의존성이 1개 줄어들 수 있기 때문입니다(MS CRT의 경우 이는 약간 문제가 됩니다).또, 콜에 관한 래핑 코드는 없습니다만, 이 영향은 무시할 수 있습니다.다시 말해, 저는 이 일을 계속하는 주된 이유가CreateThread()사용할 정당한 이유가 없다는 것입니다._beginthreadex()우선은요.기능성은 정확하거나 거의 동일합니다.

사용해야 하는 좋은 이유 중 하나_beginthread() C++ 오브젝트가 적절히 풀리거나 파괴되는 것은 (거짓으로 보인다) 경우입니다._endthread()가 호출되었습니다.

제프리 리히터로부터의 윈도 어플리케이션 디버깅을 읽으시면 거의 모든 경우에 전화하셔야 한다고 설명하십니다._beginthreadex전화하는 대신CreateThread._beginthread단순한 포장지일 뿐입니다._beginthreadex.

_beginthreadex는, CRT(C RunTime)의 내부를 초기화합니다.CreateThreadAPI로는 할 수 없다.

다음 명령어를 사용하면CreateThreadAPI를 사용하는 대신_begingthreadexCRT 함수에 대한 콜은 예기치 않은 문제를 일으킬 수 있습니다.

이 오래된 마이크로소프트 저널 From Richter를 보세요.

갱신된 질문에 대해: "전화할 수 없는 장소도 몇 군데 읽었습니다.WaitForSingleObject()내가 사용한다면_beginthread()하지만 내가 전화를 걸면_endthread()잘 되지 않을까요?"

일반적으로 스레드 핸들을 다음에 전달할 수 있습니다.WaitForSingleObject()스레드가 완료될 때까지 차단합니다.하지만 스레드 핸들은_beginthread()는 종료됩니다._endthread()가 호출됩니다(이는 명시적으로 실행할 수도 있고 스레드 프로시저가 반환되는 실행 시간까지 암묵적으로 수행됩니다).

이 문제는 다음 문서에 설명되어 있습니다.WaitForSingleObject():

대기 대기 중에 이 핸들이 닫히면 함수의 동작이 정의되지 않습니다.

이것이 핵심 코드입니다._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;
    }

기타_beginthreadex는 CRT의 스레드 단위 데이터 구조를 초기화합니다.

사용의 장점_beginthread*스레드로부터의 CRT 콜이 정상적으로 동작하는 것입니다.

함수 시그니처를 보면CreateThread와 거의 같다_beginthreadex.

_beginthread, vs

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시작점으로 설정합니다.

기억력 유출에 대한 어떤 언급도CreateThread10년이 넘었으니까 무시해야 할 것 같습니다.

흥미롭게도, 둘 다_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;
}

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

메모리 누전 등에 관한 코멘트는 모두 매우 오래된 VS2005 버전에 근거하고 있습니다.몇 년 전에 스트레스 테스트를 해봤는데 이 신화를 폭로할 수 있을 것 같아심지어 마이크로소프트도 _beginthread를 거의 사용하지 않고 예제에서 스타일을 혼합합니다.

이 코드를 사용해 보세요.

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

_beginthreadx 대신 _beginthread를 사용하면 _beginthread에 대해 너무 많은 인수를 얻을 수 있습니다.이것은 _beginthread가 보안 속성을 가진 스레드를 생성할 수 없기 때문입니다.또한 _beginthread는 불필요하다고 생각합니다.

beginthreadex실타래를 주다HANDLE에 사용하기 위해서WaitForSingleObject그리고 친구들. beginthreadDoesn't.잊지 말고CloseHandle()다 드시면요.진짜 답은 이 시스템을 사용하는 것입니다.boost::thread또는 곧 C++09의 스레드 클래스입니다.

와 비교해서_beginthread,와 함께_beginthreadex다음을 수행할 수 있습니다.

  1. 보안 속성을 지정합니다.
  2. 서스펜드 상태에서 스레드를 시작합니다.
  3. 에서 사용할 수 있는 스레드 ID를 얻을 수 있습니다.OpenThread.
  4. 콜이 성공했을 경우 반환된 스레드핸들은 유효합니다.여기서 핸들을 닫아야 합니다.CloseHandle.
  5. 반환된 스레드핸들은 동기화 API와 함께 사용할 수 있습니다.

_beginthreadex흡사하다CreateThread단, 전자는 CRT 구현이고 후자는 Windows API 호출입니다.CreateThread 매뉴얼에는 다음 권장 사항이 포함되어 있습니다.

C Run-Time Library(CRT; 런타임라이브러리)를 호출하는 실행 파일의 스레드는 스레드 관리에 및 함수를 사용해야 합니다.이를 위해서는 멀티스레드 버전의 CRT를 사용해야 합니다.를 사용하여 작성된 스레드가 CRT를 호출할 경우 CRT는 메모리 부족 상태에서 프로세스를 종료할 수 있습니다.

CreateThread()CRT가 잘못 초기화/청소되기 때문에 한때는 no-no였습니다.하지만 이것은 이제 역사다.현재 VS2010을 사용하여 (아마도 몇 가지 이전 버전을 사용하여) 문의할 수 있습니다.CreateThread()CRT를 깨지 않고요.

여기 MS 공식 확인서가 있습니다.1개의 예외가 명시되어 있습니다.

실제로 다음 명령어로 작성된 스레드에서 사용해서는 안 되는 유일한 함수는CreateThread()signal()기능.

단, 일관된 관점에서 개인적으로는 계속 사용하는 것이 좋습니다._beginthreadex().

CreateThread()는 언어 중립의 Windows API 콜입니다.OS 오브젝트 스레드를 생성하여 HANDLE을 이 스레드로 되돌립니다.모든 Windows 응용 프로그램은 이 호출을 사용하여 스레드를 만듭니다.모든 언어는 명백한 이유로 API의 직접 호출을 피합니다.1 .코드가 OS 고유의 2가 되는 것은 원치 않습니다.API를 호출하기 전에 파라미터와 결과를 변환하고 임시 스토리지를 할당하는 등의 하우스 키핑을 수행해야 합니다.

_beginthreadex()C 랩퍼인가?CreateThread()C 고유의 원인입니다.스레드 고유의 스토리지를 할당함으로써 멀티 스레드 환경에서 원래의 싱글 스레드 C f-n 작업을 가능하게 합니다.

CRT를 사용하지 않을 경우 다음 주소로 직접 전화를 걸지 않을 수 없습니다.CreateThread()CRT를 사용하는 경우,_beginthreadex()또는 일부 CRT 문자열 f-ns가 VC2005보다 이전 버전에서는 올바르게 동작하지 않을 수 있습니다.

다른 응답에서는 Win32 API 함수를 랩하는 C 런타임 함수를 호출할 때의 영향에 대해 설명하지 못했습니다.이는 DLL 로더의 잠금 동작을 고려할 때 중요합니다.

유무_beginthread{ex}는 다른 답변과 마찬가지로 특수한 C 런타임스레드/파이버 메모리 관리에 대해 설명하고 있습니까?프로세스가 아직 로드하지 않았을 가능성이 있는 DLL에 실장되어 있습니다(C 런타임에 대한 다이내믹링크를 전제로 합니다).

전화하는 것은 안전하지 않다._beginthread*부터DllMainWindows 의 「AppInit_DLLs」기능을 사용해 로드된 DLL 를 쓰는 것으로 테스트했습니다.부르기_beginthreadex (...)대신CreateThread (...)Windows 의 많은 중요한 부분이, 기동시에 기능하지 않게 됩니다.DllMain특정 초기화 작업을 수행하기 위해 로더 잠금이 해제되기를 기다리는 진입점 교착 상태.

덧붙여서, 이것은 또한 kernel32.dll이 C 런타임에서도 하는 중복되는 문자열 함수를 많이 가지고 있는 이유이기도 합니다.DllMain같은 상황을 피하기 위해서요

언급URL : https://stackoverflow.com/questions/331536/windows-threading-beginthread-vs-beginthreadex-vs-createthread-c

반응형