본문 바로가기
Dev Language/C++

Thread 생성 시 지역변수 유효 시점

by 미티치 2018. 4. 11.

함수 내에 선언된 지역 변수는 함수가 종료되는 시점에 스택에서 제거된다. ( 이것은 기본 내용 )
그래서 아래와 같이 사용하면 안됨.


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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
typedef struct tag_PIPE_INFO
{
    WCHAR wcPipeName[256];
    
}PIPE_INFO;
 
 
BOOL CPipeServer::StartPipeServer(WCHAR *wcpPipeName )
{
    DWORD        dwThreadID = 0;
    PIPE_INFO    Pipe_Info = { 0, };
 
    StringCchCopy(Pipe_Info.wcPipeName, sizeof(WCHAR)*PIPE_NAME_SIZE,  wcpPipeName);
  OutputDebugString(Pipe_Info.wcPipeName);
  
    m_hThread = ::CreateThread(
        NULL
        0,
        ConnectPipeThread,
        (LPVOID) &Pipe_Info, 
        0,
        &dwThreadID);
 
    ifNULL == m_hThread )
    {
        OutputDebugString(_T("WARNING : StartPipeServer can't create Thread."));
        return FALSE;
    }    
 
 
  OutputDebugString(_T("StartPipeServer before Sleep "));
    //Sleep(3000);    // <<- 주석
 
    OutputDebugString(_T("StartPipeServer return "));
    return TRUE;
 
}
 
 
ULONG __stdcall CPipeServer::ConnectPipeThread(LPVOID lParam)
{
    PIPE_INFO * pPipe_Info  = (PIPE_INFO *) lParam;
 
    OutputDebugString(_T("CreateNamedPipe PIPE_NAME : %s "), pPipe_Info->wcPipeName);
 
    hSvcPipe = CreateNamedPipe(
        pPipe_Info->wcPipeName, 
        PIPE_ACCESS_DUPLEX, 
        PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 
        PIPE_UNLIMITED_INSTANCES,
        PIPE_BUFF_SIZE, 
        PIPE_BUFF_SIZE,
        NMPWAIT_USE_DEFAULT_WAIT,
        NULL
    );
    
    if( hSvcPipe == INVALID_HANDLE_VALUE )
    {
        OutputDebugString(_T("WARNING : CreateNamedPipe Failed! "));
        return 0;
    }
 
  ...중략
  
  
    OutputDebugString(_T("ConnectPipeThread return 1"));
    
    return 1;
}





WCHAR Pipe_name[256] = { '\0', };
StringCchPrintf(Pipe_name , 256, _T("\\\\.\\PIPE\\PIPE_NAME"));
StartPipeServer(Pipe_name) ;
이렇게 StartPipeServer 호출 후 디버그 뷰를 확인하면

1)  \\\\.\\PIPE\\PIPE_NAME
2)  StartPipeServer before Sleep
3)  StartPipeServer return
4)  CreateNamedPipe PIPE_NAME : ???
5)  ConnectPipeThread return 1

이렇게 찍혀있다. 이런 디버그 때문에 Thread 호출부분의 함수가 종료된 후에 Thread 함수가 호출되었기 때문에
( Thread를 생성하는 함수가 종료되면 Thread 함수가 호출되는줄 알았다..)
파라미터로 넘긴 구조체 Pipe_Info가 이미 값이 없어지고 난 후라서 4번째에 PIPE_NAME 값이 제대로 안찍혔다고 생각했다.

근데 StartPipeServer 함수에서 Sleep(3000); 를 주석을 풀고 실행하면, 디버그가 아래처럼 바뀌어있다.

1)  \\\\.\\PIPE\\PIPE_NAME
2)  StartPipeServer before Sleep
3)  CreateNamedPipe PIPE_NAME : \\\\.\\PIPE\\PIPE_NAME
4)  ConnectPipeThread return 1
5)  StartPipeServer return


============================================================================
결론적으로, CreateThread를 호출해서 Thread를 생성해서 파라미터로 호출한 쪽의 지역변수(구조체)를 넘기면
호출한 쪽의 함수가 종료되기 이전까지 해당 파라미터에 저장된 값은 유효하나
호출한 함수가 종료되버리면 쓰레기 값이 되기 때문에 위와 같은 경우에는 PIPE_INFO 를 동적으로 할당해서 넘겨줘야겠지!


+ 소스 수정해서 테스트했는데 값이 잘 넘어간다.

'Dev Language > C++' 카테고리의 다른 글

C++로 DLL 만들기  (0) 2017.03.08
정적 결합과 동적 결합 & 가상함수  (0) 2016.12.23
Is a, Has a 관계 & 상속  (0) 2016.12.23
참조 변수 & 복사 생성자  (1) 2016.12.06
if문과 switch문  (0) 2016.12.06