2016-08-23 3 views
1

예를 들어, EnumWindowStations()을 보자. 호출자가 EnumWindowStationsProc() 콜백 함수를 전달해야한다. 콜백 함수는 현재 터미널 세션의 모든 윈도우 스테이션에 대해 한 번 호출됩니다. 콜백 함수의 서명을 살펴 보겠습니다 :Windows API 응용 프로그램 정의 콜백 함수에서 포인터 매개 변수 데이터의 수명은 어떻게됩니까? 콜백이 반환 된 후에도 지속됩니까?

BOOL CALLBACK EnumWindowStationProc(
    _In_ LPTSTR lpszWindowStation, 
    _In_ LPARAM lParam 
); 

첫 번째 매개 변수는 문자열 데이터에 대한 포인터입니다. 문자열 버퍼가 콜백 호출에 명시 적으로 할당 되었습니까? 콜백이 반환 된 직후에 해제되거나 열거 함수가 반환되기 직전에 해제됩니까? 또는 포인터가 어떤 종류의 영구 메모리를 가리키는 지, 문자열 버퍼가 할당 된 채 사용 가능한 상태로 남아있을 수 있습니까?

지속성이 없으면 예를 들어 콜백 및 전체 열거 프로세스가 완료된 후 액세스 할 전역 컨테이너에 원시 포인터를 저장하는 것이 올바르지 않기 때문에 이는 중요한 사항입니다. 대신 응용 프로그램에서 제어하는 ​​버퍼에 기본 문자열 데이터를 복사해야합니다. 전에 콜백이 반환됩니다.

공식 문서는 문자열 데이터의 수명이 얼마인지 명확하게 보이지 않습니다.

lpszWindowStation [에]

        윈도우 스테이션의 이름 : 매개 변수의 설명에 하나의 라인이있다.

문서 페이지에는 문자열 데이터의 수명에 관한 내용이 없습니다. 또한이 질문에 "한 번에 모두"대답하는 MSDN 페이지, 즉 Windows API의 콜백 관용구를 사용하는 모든 페이지를 찾지 못했습니다.

지금은 EnumWindowStations()/EnumWindowStationsProc() 사례에 가장 관심이 있지만 답변자가 일반적인 경우, 즉 모든 Windows API 콜백 기능에 대해 가정해야하는 경우에 가장 적합 할 것입니다.

답변

3

일반적으로 메모리가 시스템에 의해 할당되는 경우 콜백 기간 동안 유효하며 그 이상은 유효하지 않습니다. 예에서 lpszWindowStation의 경우입니다. 콜백 함수 내에서 문자열을 액세스하고 복사해야하며 콜백 외부의 시스템에서 제공 한 데이터를 참조하면 안됩니다.

조금 생각한 실험으로 이것을 추론 할 수 있습니다. 콜백이 무효화 될 때 반환 된 후이 문자열에 액세스 할 수 있습니까? 언제 할당 해제 되나요? 당신은 당신이 그것으로 끝났다고 시스템에 말해야 할 것입니다. 그 일을 지시 한 API가 없기 때문에 유일한 결론은 위에서 언급 한 것입니다.

lParam와 다른 점 이 값은 EnumWindowStations이라고 불렀을 때 제공되었으며 실제로 포인터로 사용하는 경우 포인터의 수명을 관리합니다.

+0

광산을 게시 할 때까지 답변을 알지 못했습니다. lParam에 관해서는 포인터가 아니기 때문에 어쨌든 평생의 문제는 없습니다. 포인터에 관해서는 WINAPI가 메모리를 할당하고 콜백이 그것을 해제 (또는 나중에 포인터를 저장하고 해제) 할 것으로 예상하는 몇 가지 경우가 있습니다. 그러나 이것들은 예외이며 명확하게는 –

+0

@P로 문서화됩니다. 실제로 포인터입니다. 사용자가 지정합니다. 그것이 무엇이든간에 포인터 일 가능성이 큽니다. –

+0

나는 당신의 생각 실험 아이디어를 좋아합니다. 하지만 내가 생각한 것은 어쩌면 문자열 데이터가 어딘가에 이미 메모리에 존재했을 가능성이 있습니다. 아마도 자동으로 애플리케이션과 함께로드되는 데이터 구조에있을 수 있습니다.이 경우 열거 형 함수는 포인터를 기존 메모리로 반환 할 수 있으며, 요구. (하지만 시스템 관련 데이터의 "자동 로딩"과 같은 디자인은 데이터를 전혀 사용하지 않는 응용 프로그램에 낭비가 될 수 있으므로 아마도 이해할 수 없을 것입니다 ...) – bgoldst

3

일반적으로 WINAPI에 의해 콜백 함수에 전달 된 포인터는 특정 콜백 문서에서 달리 지정되지 않는 한 콜백 기간 동안 만 유효합니다.콜백이 반환되면 포인터는 유효하지 않은 것으로 간주되어야합니다 (포인터가 해제되거나 열거 등의 다음 반복에서 덮어 쓰여질 임시 버퍼를 가리킬 수 있음).

콜백 함수는 반환 한 후에도 유지해야하는 데이터의 복사본을 생성합니다. 위의 예제의 경우 콜백이 반환 된 후에 사용해야한다면 자체 버퍼를 할당하고 lpszWindowStation의 문자열을 복사해야합니다. 물론 할당 된 버퍼의 수명도 관리해야합니다.

관련 문제