2008-11-08 2 views
2

C++ 빌더 2009에서 멀티 스레드 소켓 채팅을 작성 중입니다.
거의 완료되었지만 약간 문제가 있습니다. void *로 업 캐스트 한 CreateThread WinAPI 함수에 TMemo * 포인터를 전달해야합니다. 문제는 어떻게 내가 정말 할 수있다, NetThread 기능에 다음 C++ Builder2009에서 void *에서 TMemo *로 포인터를 올바르게 다운 캐스트 할 수 있습니까?

TMemo* MyMemo((HANDLE)lpParam); 
TMemo* MyMemo((TMemo*)lpParam); 


HANDLE xxx = MemoChat->Handle; 
hNetThread = CreateThread(NULL, 0, NetThread, xxx, 0, &dwNetThreadId); 
//... 

하고 있지만, 작업 :(

을 돌아가신`t :

나는이 방법을 tryed 이 새로운 스레드에서 내 메모 구성 요소를 사용할 수 있도록 제대로 다운 캐스팅 했습니까?

답변

3

전화 :

TMemo*  MemoChat = // You defined that somewhere I assume 
HANDLE  hNetThread = CreateThread(NULL, 0, NetThread, MemoChat, 0, &dwNetThreadId); 

여기에서 일어나고있는 것은 세 번째 매개 변수가되고 어떠한 포인터는 합격이다 자동으로 void 포인터 (또는 WinTerms LPVOID)로 변환됩니다. 시스템이 개체에 대해 알지 못하기 때문에 형식 정보가 손실됩니다.

새로운 스레드 시작 지점 : 스레드 시작 방법을

라고
DWORD NetThread(LPVOID lpParameter) 
{ 
    TMemo* MemoChat = reinterpret_cast<TMemo*>(lpParameter); 
    // Do your thread stuff here. 
} 

되면. void 포인터를 올바른 유형으로 변환하면 다시 사용할 수 있습니다.

다른 오해를 정리하십시오.

핸들은 포인터입니다.
그리고 매개 변수로 NetThread()에 전달할 수 있습니다.

HANDLE은 사용중인 개체를 가리키는 시스템 제어에서 포인터를 가리키는 포인터입니다. 그렇다면 이중 간접 검색이 필요한 이유는 무엇입니까? 그것은 시스템이 오브젝트의 모든 소유자를 찾지 않고 오브젝트를 이동시키고 포인터를 갱신 할 수있게합니다. 소유자는 방금 업데이트 한 포인터를 가리키는 포인터를 처리합니다.

주 메모리를 보조 저장소로 스왑하는 OS/하드웨어 기능으로 인해 현대 컴퓨터에서 자주 사용되지 않는 구식 컴퓨터 과학 개념입니다. 하지만 특정 리소스의 경우 여전히 유용합니다. 요즘에는 핸들이 필요할 때 사용자로부터 멀리 떨어져있는 객체 내부에 숨겨져 있습니다.

+0

나는 reintepret_cast를 사용하지 않는 것이 좋을 것이라고 생각했습니다. 그래서, 당신의 게시물은 내가 틀 렸음을 의미합니다. :) – chester89

+0

네, reinterpret_cast <>()를 사용하지 않는 것이 가장 좋지만,이 방법을 사용해야하는 몇 가지 상황 중 하나입니다. 당신이 그것을 사용해야한다는 사실은 일이 끔찍하게 잘못 될 수 있음을 보여 주며, 당신이 정말로 올바른 유형으로 캐스팅하고 있는지주의 깊게 점검해야합니다. –

+0

댓글을 주셔서 감사합니다. 많은 도움이되었습니다. – chester89

2

플리 어 HANDLE이 이 아니라이 아니라 Win32 API의 개념이라는 것을 알고 있습니다. 그래서 첫 번째 라인은 LPVOID를 HANDLE로 변환합니다. 이것은 쓰레드 루틴의 매개 변수가 실제로 핸들 (xxx)로 주어지기 때문에 정확합니다. 그런 다음 HANDLE을 MyMemo 객체로 변환합니다. 이것은 주소를 형성하는 것처럼 핸들의 비트를 처리합니다.

두 번째 줄은 정확히 동일한 변환을 수행합니다. 핸들을 포인터 인 것처럼 취급합니다.

난 당신이 스레드에 자신 MemoChat 전달되지 않은 이유를 궁금해 :

hNetThread = CreateThread(NULL, 0, NetThread, MemoChat, 0, &dwNetThreadId); 
+0

핸들이 승리하지 않습니다. 핸들은 잘 정의 된 컴퓨터 과학 개념입니다. 이것은 포인터 인 포인터입니다. 두 번째 포인터가 시스템 제어하에있는 곳. 따라서 시스템은 핸들 홀더에 영향을 미치지 않고 메모리 블록을 동적으로 이동시킬 수 있습니다. –

+0

http://msdn.microsoft.com/en-us/library/ms724457(VS.85).aspx를 참조하십시오. "각 핸들에는 내부적으로 유지 관리되는 테이블에 항목이 있습니다." Win32 HANDLE은 일반적인 CS 핸들 개념의 특정 구현입니다. –

+0

나는 그것이 정확하게 내가 전에 말했던 것이라고 생각했다! –

0

마틴이 정확하게 맞다고 생각하지 않기 때문에 핸들과 포인터의 관계를보다 명확히하려는 것이 더 좋습니다.

"포인터에 대한 포인터"는 실제로는 HANDLE이라고 불리며, 항상 액세스하는 응용 프로그램 계층에 대한 명시 적 지식없이 운영 체제가 힙 할당 메모리 블록을 물리적으로 이동할 수있게하는 일반적인 CS 방식입니다 핸들을 통해. Classic 68K Mac OS는 이러한 방식으로 작동합니다. 이런 식으로 작동하는 OS는 일반적으로 사용자 코드가 핸들을 통해 메모리를 할당 할뿐만 아니라 힙에서 직접 할당 할 수도 있습니다. 이 방법은 적절한 메모리 관리 하드웨어가없는 컴퓨터에서 사용됩니다.

그러나 이전 사용의 추상화 일부를 차용하지만 다른 구현을 사용하는 HANDLE이라는 단어가 다른 용도로 사용됩니다. 불투명 포인터 (사용자가 지식이없는 데이터 구조에 대한 포인터 - PIMPL 관용구)는 일반적으로 HANDLES라고도합니다.

또한 용어 HANDLE은 개체에 대한 "참조"를 나타내는 데 사용될 수 있습니다. 배열에 대한 인덱스 일 수 있습니다. 유닉스 파일 핸들 (= 파일 기술자)은 이것의 좋은 예입니다. stdin = 0, stdout = 1, ...

위의 Windows API 핸들은 무엇입니까? 상반된 보고서를 보았습니다. This document는 말한다 : Win32에서의

핸들이 자원이나 창을 식별 에 사용되는 숫자입니다. 그들은 포인터 또는 포인터에 대한 포인터가 아닙니다. ID 번호로 생각하십시오.

+0

Win32에서 HANDLE (typedef의 실제 이름)은 포인터 (즉 메모리 주소)가 아닙니다. 대신, 그것은 불투명 한 값입니다 - 커널 핸들의 경우 커널 메모리에있는 테이블에 대한 인덱스입니다. http://www.cs.miami.edu/~burt/journal/NT/handle_table.html –

+0

간접 참조입니다. 같은 개념의 다른 구현. –

+0

@Martin v. Lowis. 고마워요. 멋진 링크. Windows는 "typedef void * HANDLE"을 사용하여이 문제를 혼동합니다. – Roddy

관련 문제