프로그래밍/MFC

쓰레드 주의점

에어버스 2019. 3. 7. 10:52

쓰레드 주의점

1. 쓰레드로 인수 전달 주의
2. 쓰레드 호홀 시 예외발생 (ntdll.dll)

1. 아래 코드와 같이 쓰레드 호출하고 함수가 종료되는 경우
쓰레드 호출 시 지역변수 전달하면 전달 보장이 안되므로
반드시 힙, 멤버변수, 외부변수로 전달하도록 한다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <utility>
UINT ThreadFn(LPVOID arg)
{
    std::pair<CString, CString>* p = (std::pair<CString, CString>*)arg;
    CString strName1 = p->first; // 두번째 쓰레드에서 예외발생
    CString strName2 = p->second;
    return 0;
}
 
BOOL CMFCApplication1Dlg::OnInitDialog()
{
    // 기본코드
     std::pair<CString, CString> p1;
     p1.first = TEXT("1111");
     p1.second = TEXT("Test1");
     AfxBeginThread(ThreadFn, &p1);
 
     std::pair<CString, CString> p2;
     p2.first = TEXT("2222");
     p2.second = TEXT("Test2");
     AfxBeginThread(ThreadFn, &p2);
     return TRUE;
}
cs

위 코드에서 힙을 이용하여 인수를 전달

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <utility>
UINT ThreadFn(LPVOID arg)
{
    std::pair<CString, CString>* p = (std::pair<CString, CString>*)arg;
    CString strName1 = p->first; // 두번째 쓰레드에서 예외발생
    CString strName2 = p->second;
    delete p;
    return 0;
}
 
BOOL CMFCApplication1Dlg::OnInitDialog()
{
    // 기본코드
     std::pair<CString, CString> p1 = std::pair<CString, CString>(TEXT("1111"), TEXT("Test1");
     AfxBeginThread(ThreadFn, &p1);
     std::pair<CString, CString> p2 = std::pair<CString, CString>(TEXT("2222"), TEXT("Test2");
     AfxBeginThread(ThreadFn, &p2);
    return TRUE;
}
cs

 

2. 쓰레드 호홀 시 예외발생 (ntdll.dll)

아래 코드 5행 주석처럼 packet->nDataLength 만큼 힙 할당을 하면 packet->nDataLength 값이 더미값이라 쓰레드 호출하면 예외발생하므로 주의한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
BOOL CDlg::Recv_SC0(LPRECV_REAL_PACKET pRealPacket, WPARAM wParam)
{
   std::pair<CHogaBuySellDlg*, LPRECV_REAL_PACKET>* arg;
   LPRECV_REAL_PACKET packet = new RECV_REAL_PACKET;
   TCHAR* szData = new TCHAR[pRealPacket->nDataLength]; // szData = new TCHAR[packet->nDataLength]; 으로 하면 packet->nDataLength 값이 더미값일듯 하여, 반드시 pRealPacket->nDataLength 를 사용해야한다.
   arg = new std::pair<CHogaBuySellDlg*, LPRECV_REAL_PACKET>;
   memcpy(packet, pRealPacket, sizeof(RECV_REAL_PACKET));
   memcpy(szData, packet->pszData, packet->nDataLength); // memcpy(p, pRealPacket->pszData, pRealPacket->nDataLength);                
   packet->pszData = szData;
   arg->first = this;
   arg->second = packet;
 
   AfxBeginThread(쓰레드_재전송, arg);
 
   ...
}
cs