통합검색
· 마을서비스란?  · 포럼마을  · 일반마을  · 테마마을  · 마을랭킹  · 활동왕
· 덱스퍼트란?  · TECBOX   · PRSBOX   · 이용안내  
· DEXT제품군  · 솔루션베이  · S/W & ESD 컴포넌트
· 프로그램베이
· LiveSeminar  · LiveConference
Visual C++ 포럼마을 입니다.
  마을등급 Visual C++   이 마을은 포럼마을 입니다이 마을은 자유가입제 마을 입니다 마을소개 페이지로 이동 전입신청
마을촌장촌장 나성훈 주민 34024 since 2006-12-29
우리마을 공지사항
질문&답변
강좌&팁
자유게시판
자료실
앨범
개인게시판
마을 게시판
등록된 마을 게시판이
없습니다.
랑데브 게시판
칼럼 게시판
개발자 고충상담
Dev Talk
자유토론방
벼룩시장
재나미 우스개
구인/프로젝트 정보
사람인 채용 게시판
  고객지원 게시판
마이 데브피아
 나의 e-Money 내역
 활동왕 My Page
 스크랩한 게시글보기
 쪽지관리
 주소록관리

 강좌&팁
 [프로그래밍 팁 002] 64비트 윈도우즈 예외 무시 버그  | VC++ 일반 2013-09-29 오전 6:03:25
 flower_excel  flower_excel님께 메시지 보내기flower_excel님을 내 주소록에 추가합니다.flower_excel님의 개인게시판 가기 번호: 8700 추천:0  / 읽음:4,049

64비트 윈도우즈 예외 무시 버그
Exceptions that are thrown from an application that
runs in a 64-bit version of Windows are ignored


void Func1()
{
    int A = 100;
    int B = 0;
    int Result = A / B;
}

void Func2()
{
    int* p = 0x00;
    *p = 1;
}

void Func3()
{
    int arr[1024 * 1024 * 16] = {1};
}

 3 함수의 공통점은 무엇일까? 누구나 쉽게 예상할  있듯이 위의 함수들은
실행하면 크래쉬(Crash) 발생한다는 점이다. 또한 크래쉬의 순간은 덤프(Dump)라는
파일로 기록되기도 하며 덤프 분석을 통해서 쉽게 디버깅을  수도 있다.

당연히 크래쉬가 발생하지 않도록 프로그래밍을 하는 것이 이상적이긴 하지만
현실적으로 불가능하며 오히려 크래쉬 발생시 덤프를 생성하고 수집하여 문제 부분을
빠르게 수정하여 재배포를 하는 것이 가장 합리적인 대응이라고   있다. 따라서
대부분의 상용 프로그램들은 프로그램 오동작으로 인한 크래쉬 발생이나 응답없음이
발생할 경우 덤프를 생성하여 개발사에 전송할  있는 시스템을 갖춰놓고 있다.
심심하지 않게 자주   있는 인터넷 익스플로어의 오류보고 기능도 그런 일환이다.

가끔은  돌아가던 프로그램이 갑자기 중단되며 오류보고를 하겠다는 창을 띄운다면
화가 나기도 한다. 차라리 그냥 내부적으로 무시하고 다음 작업을 수행하면  좋지
않을까 생각도 들긴 하는데 오히려 그런 결과는 더욱 신뢰할  없는 결과를  수도
있다. 따라서 크래쉬를 비롯한 오동작시에는 즉시 멈추는게  낫다고   있다.

그런데! 64비트 윈도우즈에서는 위와 같은 크래쉬가 발생하지 않을 수도 있다.
필자도 개발용 PC Windows7 64비트로 변경한 이후에 위의 상황을 경험하고 나서는
상당히 당황했었다.  선에서 해결할  없었기에 끝내 Microsoft 기술지원을
문의했고 위의 문제에 어느 정도 대응할  있는 방법을 찾긴 했다.

이번 글은 위의 문제와 해결책을 소개하는 팁이 되겠다.

일단 아래의 링크를 확인해보자! 이미  문제는 어느정도 알려진 문제였다.
http://support.microsoft.com/kb/976038/en-us

위의 문서를 자세히 읽는다면  이상 아래 글은  필요가 없을 것이지만,
제대로 읽을 시간조차 없는 바쁜 개발자들을 위해서 아래에 핵심적인 내용과
해결책을 소개하려고 한다.

문서의 제목은 아래와 같다.

Exceptions that are thrown from an application that runs in a
64-bit version of Windows are ignored.

제목부터 명확하게 문제점을  설명해주고 있다. , 64비트 윈도우에서 돌아가는
프로그램에서 발생된 예외가 무시된다는 것이다.

무시라면 어떻게 무시한다는 것일까? 필자가 실험한 것에 의하면 윈도의 프로그램의
특징인 메시지루프에서  메시지를 처리하다가 예외가 발생할 경우 해당 부분에서
중단되고 메시지루프는 계속 실행되면서 다음 메시지를 처리하는 형식이다.
, 어떤 버튼을 눌렀을 경우 예외가 발생하면  순간에서  이상 버튼 처리는
무시되고 다른 버튼을 누를  있는 상태가 되는 것이다. (프로그램은 멀쩡하다.)

문서를 자세히 읽어보면 대략적인 상황을 이해할  있다.
보통 윈도우 프로시져나 훅 프로시져에서 이런 문제가 나타난다는 것이다.

An exception that is thrown in a callback routine runs in the user mode.

A user mode callback function is typically an application-defined function
that is called by a kernel mode component.

Examples of user mode callback functions are Windows procedures
and hook procedures. These functions are called by Windows to process
Windows messages or to process Windows hook events.

그런데 갑자기 궁금함이 밀려올 것이다. 필자도 느꼈지만 '이거 핫픽스는 안하나?'
사실 핫픽스 나온지는 오래되었고 Windows7 SP1에는 이미  핫픽스가 포함되어있다.
그렇다면 결국 Windows7 SP1 쓴다면 아무 문제가 없을거라고 생각하기 쉬운데,
결코 그렇지 않다는 것을 다시 한번 주의해야 한다.

문서를  자세히 읽어보면  핫픽스는 저절로 적용되는 것이 아니라 활성화를
필요로 하며 활성화 하기 위해서는 레지스트리의 특정 영역을 변경해줘야 한다.
핫픽스 SP1  설치될  자동으로 활성화까지 해주면 좋긴 하겠지만, 문제는 
활성화 되지 않은 PC들이 상당히 많다는 것이다. 일단 필자의 PC 그랬지만
회사 동료들의 64비트 PC 상당수도 같은 문제를 지닌 것을 보면  많은 경우가 
있을 같다. 각자 개발자들은 자신의 PC를 테스트할 필요가 있다.

그렇다면 전국민 64비트 PC 핫픽스 활성화 캠페인이라도 해야되는 것일까? 다행히
그럴 필요는 없고  문서는 나름의 해결책도 제시해 주고 있다. 바로 새롭게 추가된 
Kernel32.dllAPI 통해서 해당 핫픽스를 프로그램 인스턴스 단위로 활성화할  있다.

아래는 시간에 쫓기는 개발자들을 위해서 필자가 직접 문서에 제시된 API 사용하여
바로 가져다   있도록 예제 코드를 작성하였다.

#define PROCESS_CALLBACK_FILTER_ENABLED     0x1
typedef BOOL (WINAPI* PGPUMEP)(LPDWORD lpFlags);
typedef BOOL (WINAPI* PSPUMEP)(DWORD dwFlags);

void EnableHotFix()
{
    HMODULE hDLL = LoadLibrary(_T("Kernel32.dll"));

    if(hDLL)
    {
        PGPUMEP pGetProcessUserModeExceptionPolicy =
        (PGPUMEP)GetProcAddress(hDLL, _T("GetProcessUserModeExceptionPolicy"));

        PSPUMEP pSetProcessUserModeExceptionPolicy =
        (PSPUMEP)GetProcAddress(hDLL, _T("SetProcessUserModeExceptionPolicy"));

        if(pGetProcessUserModeExceptionPolicy && pSetProcessUserModeExceptionPolicy)
        {
            DWORD dwFlags;
            if(pGetProcessUserModeExceptionPolicy(&dwFlags))
            {
                pSetProcessUserModeExceptionPolicy(
                                dwFlags & ~PROCESS_CALLBACK_FILTER_ENABLED);
            }
        }
    }
}

위의 함수를 개발하는 프로그램의 시작 부분에서 실행한다면 프로그램 시작과 동시에
해당 핫픽스가 활성화되고 기존 윈도우즈 32비트 버전에서처럼 크래쉬가  발생하게
된다. , 상용 프로그램 개발시 오류보고 기능이 제대로 동작하도록 하기 위해서
필수적으로 넣어야만 하는 코드이다.

추가적으로 주의할 사항이 있다. 64비트 얘기가 나와서 헛갈릴 수도 있는데,
x64 프로그램에서 크래쉬가 무시된다는 것이 아니라 x86, x64 프로그램 둘다
64비트 윈도우즈에서 돌아갈  발생할  있는 문제라는 것이다.
, 32비트 x86 프로그램이 64비트 윈도우즈 Wow64 환경에서 에뮬레이션으로 
돌아가도 위의 문제는 발생한다는 것이다. 그러니 64비트 윈도우즈 사용자들의 
오류 덤프를 수집하기 위해서는 반드시 위와 같은 대응을 해야한다. 

 

원문 : 성남현인의 프로그래밍 원리

[코멘트] 좋음
2013-10-03 07:19
 shintx  shintx님께 메시지 보내기shintx님을 내 주소록에 추가합니다.shintx님의 개인게시판 가기 
가장 좋은것은 Static Release로 죽지 않는 프로그램을 배포하는겁니다.
버그 있는 프로그램을 수선하는데 인생을 낭비하지 말아야 합니다.

---------------------------------------------------------------------
그리고. 이 코드에서의 문제로 해보면 안됩니다. try 에서 그냥 멈춰 버립니다.
제가 잘못 확인하는건지 모르겠습니다. ㅇ_ㅇ??

예상대로라면. try catch 이면. catch로 잡혀야 하는데. 그냥 이런 에러로 종료 되네요.
test.exe의 0x004115aa에 첫째 예외가 있습니다. 0xC0000094: Integer division by zero
test.exe의 0x004115aa에 처리되지 않은 예외가 있습니다. 0xC0000094: Integer division by zero

보고 하기 전에 죽습니다. 어떻게 해야 하는지 방식을 알아야 할거 같습니다.

#include < windows.h >

#define PROCESS_CALLBACK_FILTER_ENABLED 0x1
typedef BOOL (WINAPI* PGPUMEP)(LPDWORD lpFlags);
typedef BOOL (WINAPI* PSPUMEP)(DWORD dwFlags);

void EnableHotFix()
{
HMODULE hDLL = LoadLibrary(_T("Kernel32.dll"));

if(hDLL)
{
PGPUMEP pGetProcessUserModeExceptionPolicy =
(PGPUMEP)GetProcAddress(hDLL, _T("GetProcessUserModeExceptionPolicy"));

PSPUMEP pSetProcessUserModeExceptionPolicy =
(PSPUMEP)GetProcAddress(hDLL, _T("SetProcessUserModeExceptionPolicy"));

if(pGetProcessUserModeExceptionPolicy && pSetProcessUserModeExceptionPolicy)
{
DWORD dwFlags;
if(pGetProcessUserModeExceptionPolicy(&dwFlags))
{
pSetProcessUserModeExceptionPolicy(
dwFlags & ~PROCESS_CALLBACK_FILTER_ENABLED);
}
}
}
}
void Func1()
{
try
{
int A = 100;
int B = 0;
int Result = A / B;
}
catch(char* a)
{
EnableHotFix();
}
}

void Func2()
{
try
{
int* p = 0x00;
*p = 1;
}
catch(char* a)
{
EnableHotFix();
}
}

void Func3()
{
try
{
int arr[1024 * 1024 * 16] = {1};
}
catch(char* a)
{
EnableHotFix();
}
}

int _tmain(int argc, _TCHAR* argv[])
{
try
{
Func1();
Func2();
Func3();
}
catch(char* a)
{
EnableHotFix();
}

return 0;
}
저장 취소
[코멘트] 좋음
2013-10-04 10:43
 leesa49  leesa49님께 메시지 보내기leesa49님을 내 주소록에 추가합니다.leesa49님의 개인게시판 가기 
http://support.microsoft.com/kb/976038/en-us 여기글 잘보았습니다
저장 취소
[코멘트] 좋음
2013-10-04 11:05
 win3200  win3200님께 메시지 보내기win3200님을 내 주소록에 추가합니다.win3200님의 개인게시판 가기 
곧 Fix 올라오겠죠
저장 취소
[코멘트] 좋음
2013-10-07 17:12
 TohnoKanna  TohnoKanna님께 메시지 보내기TohnoKanna님을 내 주소록에 추가합니다.TohnoKanna님의 개인게시판 가기 
흠 치명적이군요
저장 취소
코멘트쓰기
  좋음   놀람   궁금   화남   슬픔   최고   침묵   시무룩   부끄럼   난감
* 코멘트는 500자 이내(띄어쓰기 포함)로 적어주세요.
목록 보기   지금 보고 계시는 글을 회원님의 my Mblog >> 스크랩에 넣어두고 다음에 바로 보실 수 있습니다.  
회사소개  |   개인정보취급방침  |  제휴문의  |   광고문의  |   E-Mail 무단수집거부  |   고객지원  |   이용안내  |   세금계산서
사업자등록번호 안내: 220-81-90008 / 통신판매업신고번호 제 2017-서울구로-0055호 / 대표: 홍영준, 서민호
08390, 서울시 구로구 디지털로32길 30, 1211호 / TEL. 02_6719_6200 / FAX. 02-6499-1910
Copyright ⓒ (주) 데브피아. All rights reserved.