요즘 한창 작업하고 있는 프로젝트의 프로그램이 조금 복잡한 형태를 띄고 있다.
문제는 '실제기능.dll'이 'MFC컨트롤.dll'에 있는 CDialog를 상속한 CInputNumberDlg를 사용할 때 발생했다.
Modeless로 사용하는 때는 전혀 문제가 없는데.. DoModal로 사용했을 때 문제가 발생했다.
Debug 모드에서는 전혀 문제가 없는데 Release 모드에서는 DoModal만 하면 그냥 프로그램이 죽어버리는 것이다.
이런 경우가.. 디버그는 되는데 릴리즈가 안돼!
그래서 약간의 검색을 통해보니 DLL에서 MFC 컨트롤을 사용하려면 아래와 같은 코드를 매 함수마다 다 넣어야 한다고 한다.
그냥 DoModal만 상속받아서 넣어봤다.
그랬더니 컴파일이 안돼!
그래서 다시 검색해 보니 MFC 확장 DLL에서는 AfxGetStaticModuleState 대신에 AfxGetAppModuleState를 사용하라고 하네..
http://support.microsoft.com/kb/161589
그래서 사용했더니 잘되는듯이 보....였지만!!
이번에는 릴리즈에서는 되는데 디버그에서 안돼!
디버그로 실행시 대화상자를 닫을 때 wincore.cpp의 1027번 라인에서 Assertion 발생.
머냐..
또 한참동안 검색 시작..
비슷한 문제를 가진 사람을 다수 찾았지만 그냥 다 추측만 할 뿐 해결책은 없었다.
그나마 아래의 질문이 가장 가까운 문제였지만..
http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/f0f31ba2-cd7a-4bad-8442-eb08d90ee0d6
결국 결론은 "그냥 MFC확장DLL 쓰셈"이라니..
이봐.. 내 경우에는 이미 둘다 MFC확장DLL이다.
뭘 어쩌란 말인가..
곰곰히 생각을 해봤다.
아무래도 MS가 지나치게 복잡하게 만들어버린 MFC의 리소스 관리가 문제가 아니겠는가?
무언가 매핑이 이상하게 이루어져서 실행하는 쪽 리소스맵에는 있는데 DoModal이 실행되는 쪽 리소스맵에는 없는 그런 사태일 것이다.
그렇다면 생성할 때도 AfxGetAppModuleState를 전부 실행해 주면 어떨까?
하는 생각에 모든 생성자와 메서드들에 다 추가 시켜봤더니. 정작 DoModal을 제외한 다른 모든 부분에서 오류를 뿜으며 죽는 사태가..
그렇다면!
DoModal을 하는 대화상자만 AfxGetAppModuleState 아래에서 실행되게 하는 것이닷!
흐음.. 대충 써보니 잘된다. 고쳐야할 코드량을 최소화 시킬 수 있어서 나름 만족스럽다.
이번에도 어렵게 해결.
안 쓰던 MFC를 쓰려니 골병들겠네.. 역시 나에겐 윈도우즈 프로그래밍은 Win32 API가 최고.
문제는 '실제기능.dll'이 'MFC컨트롤.dll'에 있는 CDialog를 상속한 CInputNumberDlg를 사용할 때 발생했다.
Modeless로 사용하는 때는 전혀 문제가 없는데.. DoModal로 사용했을 때 문제가 발생했다.
Debug 모드에서는 전혀 문제가 없는데 Release 모드에서는 DoModal만 하면 그냥 프로그램이 죽어버리는 것이다.
이런 경우가.. 디버그는 되는데 릴리즈가 안돼!
그래서 약간의 검색을 통해보니 DLL에서 MFC 컨트롤을 사용하려면 아래와 같은 코드를 매 함수마다 다 넣어야 한다고 한다.
그냥 DoModal만 상속받아서 넣어봤다.
INT_PTR CInputNumberDlg::DoModal()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return CDialog::DoModal();
}
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return CDialog::DoModal();
}
그랬더니 컴파일이 안돼!
mfcs90u.lib(dllmodul.obj) : error LNK2005: _DllMain@12이(가) dllmain.obj에 이미 정의되어 있습니다.
그래서 다시 검색해 보니 MFC 확장 DLL에서는 AfxGetStaticModuleState 대신에 AfxGetAppModuleState를 사용하라고 하네..
http://support.microsoft.com/kb/161589
INT_PTR CInputNumberDlg::DoModal()
{
AFX_MANAGE_STATE(AfxGetAppModuleState());
return CDialog::DoModal();
}
{
AFX_MANAGE_STATE(AfxGetAppModuleState());
return CDialog::DoModal();
}
그래서 사용했더니 잘되는듯이 보....였지만!!
이번에는 릴리즈에서는 되는데 디버그에서 안돼!
디버그로 실행시 대화상자를 닫을 때 wincore.cpp의 1027번 라인에서 Assertion 발생.
문제의 코드
머냐..
또 한참동안 검색 시작..
비슷한 문제를 가진 사람을 다수 찾았지만 그냥 다 추측만 할 뿐 해결책은 없었다.
그나마 아래의 질문이 가장 가까운 문제였지만..
http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/f0f31ba2-cd7a-4bad-8442-eb08d90ee0d6
결국 결론은 "그냥 MFC확장DLL 쓰셈"이라니..
이봐.. 내 경우에는 이미 둘다 MFC확장DLL이다.
뭘 어쩌란 말인가..
곰곰히 생각을 해봤다.
아무래도 MS가 지나치게 복잡하게 만들어버린 MFC의 리소스 관리가 문제가 아니겠는가?
무언가 매핑이 이상하게 이루어져서 실행하는 쪽 리소스맵에는 있는데 DoModal이 실행되는 쪽 리소스맵에는 없는 그런 사태일 것이다.
그렇다면 생성할 때도 AfxGetAppModuleState를 전부 실행해 주면 어떨까?
하는 생각에 모든 생성자와 메서드들에 다 추가 시켜봤더니. 정작 DoModal을 제외한 다른 모든 부분에서 오류를 뿜으며 죽는 사태가..
그렇다면!
DoModal을 하는 대화상자만 AfxGetAppModuleState 아래에서 실행되게 하는 것이닷!
// 헤더 파일
class AFX_EXT_CLASS CInputNumberDlg : public CDialog
{
DECLARE_DYNAMIC(CInputNumberDlg)
public:
CInputNumberDlg(CWnd* pParent = NULL); // 표준 생성자입니다.
virtual ~CInputNumberDlg();
static CInputNumberDlg* NewModal(CWnd* pParentWnd = NULL); // <-- 대화상자 생성기 추가!
// ...
};
// 코드 파일
CInputNumberDlg* CInputNumberDlg::NewModal(CWnd* pParentWnd)
{
AFX_MANAGE_STATE(AfxGetAppModuleState());
return (new CInputNumberDlg(pParentWnd));
}
// 사용하기
CInputNumberDlg* dlg = CInputNumberDlg::NewModal(); // <-- 요렇게 생성해서
dlg->SetTitle(getMenuTitle(idx));
dlg->SetMessage(_T("Input distance"));
dlg->SetInputUnit(_T("m"));
dlg->SetInputRange(dist_st, dist_en, 1000);
if (IDOK == dlg->DoModal()) // <-- 요렇게 쓴다
{
dist_cur = dlg->GetInput();
delete dlg; // <-- 꼭 삭제하기
return navi.gotoDist(dist_cur);
}
delete dlg; // <-- 꼭 삭제하기
class AFX_EXT_CLASS CInputNumberDlg : public CDialog
{
DECLARE_DYNAMIC(CInputNumberDlg)
public:
CInputNumberDlg(CWnd* pParent = NULL); // 표준 생성자입니다.
virtual ~CInputNumberDlg();
static CInputNumberDlg* NewModal(CWnd* pParentWnd = NULL); // <-- 대화상자 생성기 추가!
// ...
};
// 코드 파일
CInputNumberDlg* CInputNumberDlg::NewModal(CWnd* pParentWnd)
{
AFX_MANAGE_STATE(AfxGetAppModuleState());
return (new CInputNumberDlg(pParentWnd));
}
// 사용하기
CInputNumberDlg* dlg = CInputNumberDlg::NewModal(); // <-- 요렇게 생성해서
dlg->SetTitle(getMenuTitle(idx));
dlg->SetMessage(_T("Input distance"));
dlg->SetInputUnit(_T("m"));
dlg->SetInputRange(dist_st, dist_en, 1000);
if (IDOK == dlg->DoModal()) // <-- 요렇게 쓴다
{
dist_cur = dlg->GetInput();
delete dlg; // <-- 꼭 삭제하기
return navi.gotoDist(dist_cur);
}
delete dlg; // <-- 꼭 삭제하기
흐음.. 대충 써보니 잘된다. 고쳐야할 코드량을 최소화 시킬 수 있어서 나름 만족스럽다.
이번에도 어렵게 해결.
안 쓰던 MFC를 쓰려니 골병들겠네.. 역시 나에겐 윈도우즈 프로그래밍은 Win32 API가 최고.
'스킬북 > 개발 정보' 카테고리의 다른 글
| [오류열전] MFC DLL의 CDialog에서 DoModal시 오류 발생 (1) | 2011/10/26 |
|---|---|
| 안드로이드 AVD 실행 오류 (1) | 2011/03/28 |
| [오류열전] OpenGL 텍스쳐에서 주의할 점 (1) | 2010/10/25 |
| [오류열전] File: wincore.cpp Line: 906 (0) | 2010/10/13 |


|꼬마늑대|


댓글을 달아 주세요
자바 쓰세요 ~