티스토리 뷰

반응형


CreateThread()와 _beginthreadex()는 모두 Windows에서 새 스레드를 만드는 함수입니다.
하지만 이 둘은 내부적으로 완전히 다른 용도이며,
사용 대상, 메모리 관리, 안정성 면에서 차이가 뚜렷합니다.

아래에 단순 기능 나열이 아니라,
왜 두 개가 존재하는지, 언제 어떤 걸 써야 하는지,
그리고 뭘 잘못 쓰면 무슨 문제가 생기는지까지 설명드리겠습니다.


🔧 1. 기본 개념부터 — 둘 다 스레드를 만든다

함수 이름 역할

CreateThread() Windows API에서 제공하는 원시(low-level) 스레드 생성 함수
_beginthreadex() C 런타임 라이브러리(C Runtime, CRT)에서 제공하는 C/C++ 전용 스레드 생성 함수

🚨 2. 왜 둘 다 있어야 하냐?

이 질문이 핵심입니다.
대답은 명확합니다:

CreateThread()는 Windows OS 입장에서 “스레드를 하나 만들었다”는 관점.
_beginthreadex()는 C/C++ 런타임까지 포함해서 “C/C++에서 안전하게 쓸 수 있는 스레드”를 만드는 함수.


🧠 3. 뭐가 다르냐? (기술적으로)

✅ A. C 런타임 라이브러리(CRT) 초기화

  • CreateThread()는 CRT에 아무 통보도 안 함.
    즉, malloc, printf, errno, atexit 같은 C 함수들이 동작할 수 있게 해주는 구조 초기화가 안 됨.
  • _beginthreadex()는 스레드 내부에서 사용할 CRT 상태(예: errno, locale, static buffer) 를 준비함.
    → printf, strtok, new, delete, iostream 등 다 안전하게 사용 가능.

📌 즉, CreateThread() 안에서는 malloc/printf 쓰는 순간 프로그램이 죽을 수도 있음.


✅ B. 스레드 종료 시 자원 정리

  • CreateThread()는 스레드 함수가 끝나면 OS 레벨로 리턴할 뿐,
    C 런타임에 “나 종료함” 이라고 알리지 않음.
    → 그래서 메모리 누수(memory leak) 발생 가능.
  • _beginthreadex()는 끝날 때 endthreadex()를 호출해서
    C 런타임이 사용한 리소스를 전부 반납함.

💣 4. 실전에서 CreateThread 잘못 쓰면 이런 일 생김

예시: CreateThread()로 만든 스레드 안에서 printf() 호출

DWORD WINAPI ThreadFunc(LPVOID p) {
    printf("hello\n");  // CRT 상태 없이 실행하면 터질 수도 있음
    return 0;
}

→ 이건 운 좋으면 돌아가고, 운 나쁘면 조용히 크래시 납니다.
특히 디버깅 어려운 프로그램일수록 랜덤하게 죽는 증상이 생깁니다.
이유는: CRT 내부 상태(static thread-local buffer 등)가 초기화되지 않았기 때문.


🧪 5. 사용법 차이

▶ CreateThread()

HANDLE h = CreateThread(
    NULL, 0, ThreadFunc, NULL, 0, NULL);

함수는 다음 형태여야 함:

DWORD WINAPI ThreadFunc(LPVOID lpParam);

▶ _beginthreadex()

unsigned threadID;
HANDLE h = (HANDLE)_beginthreadex(
    NULL, 0, ThreadFunc, NULL, 0, &threadID);

함수는 다음 형태여야 함:

unsigned __stdcall ThreadFunc(void* param);

🚨 함수 시그니처 다름 주의! DWORD vs unsigned, LPVOID vs void*


✅ 6. 요약 비교표

항목 CreateThread() _beginthreadex()

라이브러리 Windows API C/C++ CRT
CRT 초기화 ❌ 없음 ✅ 있음
스레드 종료 시 정리 ❌ 직접 해줘야 함 ✅ 자동 정리 (endthreadex())
안전성 ❌ CRT 함수 쓰면 위험 ✅ 안전
리턴값 HANDLE uintptr_t (실제로는 HANDLE로 캐스팅 가능)
함수 형태 DWORD WINAPI unsigned __stdcall

🔨 언제 뭐 써야 되냐?

상황 써야 할 함수

C/C++ 프로그램, printf, malloc, new/delete 등 쓰면 _beginthreadex()
Win32 API만 사용하는 순수 Windows 프로그래밍 CreateThread() 가능
성능보다 안정성이 중요함 _beginthreadex() 추천
콘솔 프로그램, MFC, ATL 등 대부분의 C++ 앱 무조건 _beginthreadex() 써야 안전

🧾 마무리 요약

  • CreateThread()는 Windows가 만든 낮은 수준의 스레드 생성 함수
  • _beginthreadex()는 C/C++ 프로그램에서 안전하게 쓸 수 있게 만든 CRT 친화적 스레드 함수
  • 스레드 안에서 malloc, printf, std::cout, new, delete 쓸 거면
    무조건 _beginthreadex() 써야 안전

 

반응형

'프로그래밍 > 시스템 프로그래밍' 카테고리의 다른 글

API란 무엇인가?  (0) 2025.04.05
__stdcall 이란?  (0) 2025.04.05
프로세스와 스레드  (0) 2025.03.31
파이프 방식의 IPC  (0) 2025.03.27
프로세스, 핸들 테이블, 그리고 핸들 상속  (0) 2025.03.26
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함
반응형