| |
|
|
|
|
|
아래 프로그램은 쭌이 최근 진행중인 프로젝트에 필요해서 만든 시리얼 생성 및 검증 프로그램이다.
컴퓨터에 설치된 네트워크 인테페이스 카드의 맥 주소를 시리얼 키 생성의 소스로 사용함으로서 해당 시리얼 키는 생성시 지정한 네트워크 카드가 설치된 시스템에서만 유효하게 된다.
이때 시스템에 있는 네크워크 인터페이스 카드를 나열하기 위해 ComboBox를 사용하였다. 아래 보이는 그림처럼 디폴트 Style은 Sort 속성이 true로 되어 있다.
즉, AddString() 메서드를 사용해 Combo Item을 추가하면 자동으로 정렬이 된다.
다음은 WMI를 이용 시스템에 설치된 네트워크 카드를 검색하면서 ComboBox(m_ctrlEtherList_Combo) 에 검색된 네트워크 카드의 Description을 추가하는 소스의 일부이다.
또한 시리얼 키의 중요한 데이타인 맥 주소들을 기억하기 위해 ComboBox의 SetItemDataPtr() 메서드를 이용 다른 코드에서 맥 주소 참조가 가능하도록 해 주었다.
결론적으로 이 코드는 심각한 버그를 가지고 있다.
[CODE] CoInitialize(NULL); try { WbemScripting::ISWbemLocatorPtr locator; locator.CreateInstance(WbemScripting::CLSID_SWbemLocator); if (locator != NULL) { WbemScripting::ISWbemServicesPtr services = locator->ConnectServer(".","root\\cimv2","","","","",0,NULL); WbemScripting::ISWbemObjectSetPtr objects = services->ExecQuery("Select * from Win32_NetworkAdapter where AdapterTypeID = 0 and Description != 'Packet Scheduler Miniport' and Description != '패킷 스케줄러 미니 포트'","WQL",0x10,NULL); IEnumVARIANTPtr obj_enum = objects->Get_NewEnum(); ULONG fetched; VARIANT var; int count = 0; while (obj_enum->Next(1,&var,&fetched) == S_OK) { WbemScripting::ISWbemObjectPtr object = var; WbemScripting::ISWbemPropertySetPtr properties = object->Properties_; WbemScripting::ISWbemPropertyPtr prop = properties->Item("Description",0); m_ctrlEtherList_Combo.AddString( (const char*)_bstr_t(prop->GetValue())); prop = properties->Item("MACAddress",0); CString *pMacAddress = new CString( (const char*)_bstr_t(prop->GetValue())); m_ctrlEtherList_Combo.SetItemDataPtr(count,pMacAddress); count++; } } } catch (_com_error err) { CString msg = _T("WMI Query Error ocured: "); msg += err.ErrorMessage(); AfxMessageBox(msg); CoUninitialize(); return FALSE; } CoUninitialize(); if(m_ctrlEtherList_Combo.GetCount() > 0) { m_ctrlEtherList_Combo.SetCurSel(0); m_strMacAddress = *((CString*)m_ctrlEtherList_Combo.GetItemDataPtr(0)); m_strSerialKey = GetSerialKey(m_strMacAddress); UpdateData(FALSE); } [/CODE]
Line 49 : m_strMacAddress = *((CString*)m_ctrlEtherList_Combo.GetItemDataPtr(0));
에서 런타임 시 Assertion 에러가 발생한다.
개발에 쓰인 내 컴에서는 천만 다행(--;)으로 에러 없이 통과 했던 코드가 쭌 시스템에서 바로 폭발하였다. 도대체 무엇 때문일까? 코드의 어느 부분이 잘못된 것일까?
바로 원인은 Line 31 : m_ctrlEtherList_Combo.SetItemDataPtr(count,pMacAddress); 에 있었다.
다음의 시나리오를 가정해 보자.
* 시스템에 3개의 네트워크 인터페이스가 있다.
* WMI로 검색하면 다음의 순으로 인터페이스를 리턴한다. 0. Realteck Fast Ethernet 1. Intel Wireless Fast Ehternet 2. 3Com Fast Ethernet
* ComboBox 에 들어가면서 정렬된다면 다음의 순이 될 것이다. 0. 3Com Fast Ethernet 1. Intel Wireless Fast Ehternet 2. Realteck Fast Ethernet
만약 Line 31을 다음과 같이 수정하여 디버깅 한다면 3번 모두 0을 리턴할 것이다. Line 31 : int iIndex = m_ctrlEtherList_Combo.SetItemDataPtr(count,pMacAddress);
따라서 Line 49에서 에러가 발생한 이유가 설명된다.
새로 추가한 아이템은 계속 0번째에 추가되며, 다른 아이템들을 밀어 내는데 count를 1나씩 증가하면서 맥 주소를 설정해 줌으로서 결과적으로 맥 주소는 2번째 Item에만 설정되고, 0번째, 1번째 item에는 설정되지 않게 된것이다.
이때 Line 49에서 0번째 Item의 맥 주소를 받을려고 하는데, 쓰레기 값이나 NULL 값이 리턴됨으로서 잘못된 메모리 주소가 되어 에러가 발생한 것이다.
그렇다면 sort 속성과 상관 없이 코드가 옳바르게 동작할려면 어떻게 고쳐야 할까?
[CODE] int iIndex = m_ctrlEtherList_Combo.AddString( (const char*)_bstr_t(prop->GetValue())); prop = properties->Item("MACAddress",0); CString *pMacAddress = new CString( (const char*)_bstr_t(prop->GetValue())); m_ctrlEtherList_Combo.SetItemDataPtr(iIndex,pMacAddress); [/CODE]
첫 코드 처럼 count로 속단하고 index를 순차적으로 늘리는 것은 잘못된 방법이다.
AddString 함수는 Item 추가후 해당 item이 최종적으로 위치하게 된 Index를 리턴해 준다. sort 속성이 false 라면 0 부터 순차적으로 늘어날 것이며, true라면 정렬이 이루어진 후의 0부터 몇 번째에 위치하는지의 값을 리턴해 줄 것이다.
따라서 Line 1 : int iIndex = m_ctrlEtherList_Combo.AddString( (const char*)_bstr_t(prop->GetValue()));
AddString() 메서드의 리턴 값을 받아 옳바른 Index 값을 얻은 후 Line 6 처럼 해당 Index 값을 사용하여 연관된 다른 동작을 하는 것이 문제가 발생할 소지를 없앨 수 있다.
Line 6 : m_ctrlEtherList_Combo.SetItemDataPtr(iIndex,pMacAddress);
MFC의 ComboBox 나 ListBox 사용시 AddString() 다음에 index값을 가지고 다른 기능을 하고자 할때는 반드시 AddString의 리턴 값을 index로 사용하자.
|
|
|
| Track this back : http://www.codeforum.net/blog/pitoosung/trackback/95 |
|
|
|
|
«
2010/09
»
| 일 |
월 |
화 |
수 |
목 |
금 |
토 |
| |
|
|
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 |
|
|
|
Total : 70560
Today : 54
Yesterday : 46 |
|
|
|