개발자 면접 문제 중...

Find three ways to change one character in the following code so that the resulting
code will print exactly 20 minus signs

Remember: for each solution you can only change "one" character from this original code:

int
i, n=20;
for(i =0 ; i < n ; i--)
  printf
("-");

: 인텔 개발자 인터뷰에서 나온 문제랍니다!^^ 자신은 과연 몇 개나 생각했나요?ㅋ

more..


출처: http://theeye.pe.kr/
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 노헝그리

2008/06/27 11:15 2008/06/27 11:15
,
Response
44 Trackbacks , a comment
RSS :
http://www.nohungry.net/tt1/rss/response/130

 우연히 웹서핑을 하던 도중, Visual Leak Detector란 녀석을 알게 되었다.
(사실, 제법 이전부터 알고는 있었지만, 쓰지는 않았다.)

사용법은 매우 단순하다. 코드에 #inclue <vld.h>를 추가해주고, 디버그 모드로 돌려보면, Memory Leak이
존재할 경우, 사정없이 뱉어준다.


이 녀석을 이용해, 현재 구현중이던 프로그램에 적용해보니, Memory Leak이 발견되었다는 것이 아닌가?!
허거덩..-_- 분명, MS 자체의 디버그 모드로 돌렸을 때는 발견되지 않았었는데..!!!

"뭐야뭐야! 나같은 천재에게 Memory Leak은 어울리지 않아-ㅁ-;; 분명, Visual Leak Detector의 버그 일거
야..-ㅁ-" 같은 헛소리를 하면서.. 차근차근 Memory Leak이 발생할만한 원인을 탐색하던 바... 이르게 된 곳
은 STL의 ifstream이었다.


난 모든 코드를 배제하고, MFC의 Dialog 기반의 프로젝트를 하나 생성했다. 그리고, 단지 2줄의 코드만 추
가했다.

ifstream fin("sample.txt");
fin.close();

그랬음에도.. 우리의 Visual Leak Detector는 Memory Leak을 찾아냈다. 여기에도 또 문제가 있는 것이,
"sample.txt"란 파일이 존재할 경우에만, Memory Leak을 뱉어냈다. 즉, 존재하지 않는 파일의 경우엔 파일
Open을 해도 Memory Leak을 뱉어내지 않았다.

나는 확인을 위해.. 데브피아에서 질문을 올렸는데..

A님: Visual Leak Detector를 사용해보지는 않았으나 바운스체커도 메모리릭이 발견되네요. stl부분에서

B님:

VS6.0에 포함되어 있는 STL 버전이 상당히 구닥다리 입니다.

딩컴웨어의 구닥다리 버전이 포함되어 있어서 6.0에서는 stl을 사용할때

외부 STL을 사용하곤 했지요..

STL_Port 같은것을 사용하세요..


2003 이상 버전에서 포함되어 있는 STL을 그대로 쓰셔도 상관 없습니다.


친절하게 두 분의 답변이 돌아왔다. 결국엔 Visual Studio 6.0에 포함되어 있는 STL에 문제가 있는 것이다.
난 좀 더 확인을 위해 (왜케 집요해졌는지 모르겠다.) 짧은 영어로 MSDN을 헤맸는데, Visual Studio 6.0에서
STL string으로 Multi-Thread 프로그램을 구현할 경우, Memory Corruption이 발생할 수 있다는 MS의 얘기를
발견할 수 있었다.
MS에서 제시하는 해결책 역시 데브피아에서 B님이 답변해준 것과 비슷하게, Visual Studio 2003 이상 버전
을 쓰거나 STL 3rd party 라이브러리를 쓰라는 얘기였다.

난 이제 껏, STL하면, SGI STL이 전부인줄 알았을 정도로 참으로 무지했다.
알고보니, gcc는 SGI STL을 기반으로 gcc 컴파일러에 맞게 구현해놓은 것을 쓰고 있고, MS는
Dinkumware 사의 STL을 쓰고 있었다. 그리고, Borland C++ Builder는 최근까지 Roguewave의
STL을 쓰다가, STL Port로 넘어갔다.

C++ 표준이 되어버린 STL일지라도 각 회사마다 STL은 조금씩 특징이 있었다.
대표적으로 STL Port와 Dinkumware의 STL의 list<> 클래스의 list 크기를 반환하는 size() 함수를 예로 들
면.. (http://crowmaniac.net/crowmania/ 를 참고한 어느 분의 블로그에서 참고했습니다.)

Dinkumware 사의 STL에서 제공하는 list의 size() 함수는 시간 복잡도가 O(1)이었다.
size_type size() const{   return (_MySize);   }

반면에, STL Port에서 제공하는 list의 size() 함수는 시간 복잡도가 O(n)이었다.
size_type size() const
{
       size_type _result = distance(begin(), end());
       return _result;
}

distance() 함수가 Bidirectional iterator기 때문에 O(n)인 것이다.

잉?! 그럼, 두 말 할 나위 없이, Dinkumware 사의 STL이 좋은 것이냐?
꼭, 그런 것은 아니다..^^

size()를 O(1)으로 구현한 Dinkumware 사의 STL은 태생적으로 O(n)의 splice(끼워넣기)를 가지는 반면에,
STL Port는 O(1)의 splice만 가진다.

다시 얘기하면, size()를 자주 호출해야할 코드에서는 Dinkumware의 STL이 낫고, splice를 자주해야 하는
코드에서는 STL Port가 낫다고 볼 수 있다.

뭐, 난 갠적으로 정렬이 필요하지 않은 데이터의 경운 걍 vector를 쓰고, 정렬이 필요한 경우엔 Hashtable을
구현한 map을 쓰기 때문에-ㅁ-;; list를 잘 쓰지 않는다.

암튼.. 이제 STL Port를 깔러 가야겠다-ㅁ-

크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 노헝그리

2007/11/28 17:20 2007/11/28 17:20
, , ,
Response
84 Trackbacks , 8 Comments
RSS :
http://www.nohungry.net/tt1/rss/response/117

우리 회사에서 개발 중인 무선 계측기는 검색 기능을 제공하는데, 검색 방법은 UDP 프로토콜을 이용한 브로드캐스팅이다. 짜증스럽게도, UDP 프로토콜로 브로드캐스팅을 하기 위해서는 IP 대역이 맞아야 한다.

우리의 사랑스런(?) 무선계측기들은 IP가 192로 시작하고... 우리 회사의 PC들은 고정 IP를 사용하는데.. 211로 시작한다. 따라서, 무선계측기를 테스트하려고 하면, 항상 IP를 바꿔주는 노가다가 필요하다. 단지, UDP로 브로드캐스팅을 하기 위해서..-_-

일일이 네트워크 환경 - 설정 - TCP/IP 설정..... 으로 이어지는 귀차니즘을 이기지 못하고, 알아본바.. WMI라는 녀석을 알게 되었다.

WMIWindows Management Instrumentation인데, Windows 기반 운영체제의 management 데이터를 위한 인프라 구조라고 할 수 있다.

쉽게, 예를 들자면.. 내 운영체제의 버전이 얼마인지? 또는 내 컴퓨터의 IP를 변경하고 싶다던지? 내지는 원격으로 컴퓨터에 프로그램을 설치하고 싶다던지... 이 모든 것이 다 WMI로 가능하다는 것이다.

더 상세한 내용은 MSDN을 참고하기로 하고.. 이미 이전에 WMI를 이용해 C#으로 간단히 IP와 서브넷 마스크, 게이트웨이 등을 설정할 수 있는 프로그램을 만든 바가 있어서 C++로도 간단히 1~2시간이면 할 수 있을거라 여겼다.

하지만, Wrapper Class와 많은 예제가 제공되던 C#과는 달리, C++에서는 WMI가 완전히 COM API 레벨에서 해결해야 하고, 내가 원하는 수준의 예제가 없었다. (내가 못 찾은건지도 모른다-ㅁ-)

그러다보니.. 삽질에 삽질을 거듭하다.. 결국 야근까지 하게되며.. 무려 6시간을 잡고 헤맸다.

잡설이 길었는데.. WMI를 이용해 Local PC의 IP를 바꾸는 내용으로 돌아와서...

구현 환경은 Windows XP Professional, Microsoft Visual Studio 6.0 SP6이다.
내 기억이 맞다면, Microsoft Visual Studio 6.0에서 WMI를 구현하기 위해서는 아마도 Microsoft Platform SDK 또는 WMI SDK를 설치해야 하는 것으로 알고 있다.

그리고 코드의 전체적인 흐름은 다음과 같다.

Step 1. COM 라이브러리를 초기화한다.
Step 2. COM Security Level을 설정한다.
Step 3. WMI에 대한 초기 Locator를 획득한다.
Step 4. WMI에 접근한다.
Step 5. Proxy의 Security Level을 설정한다.


여기까지는 사실, WMI를 프로그래밍 하기 위한 준비 단계라 할 수 있다. 이 다음부터는, IP와 서브넷마스크를 설정하기 위한 단계이다.

Step 6. ExecQuery()를 이용해, Class Object Enum을 가져온다.

hr = pServices->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_NetworkAdapterConfiguration"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnum
);

쉽게 설명하면, Win32_NetworkAdapterConfiguration란 클래스로부터 Network Adpater들의 Enum을 가져온다고 볼 수 있다. WMI의 Win32 Class에 대한 보다 상세한 정보는 http://msdn2.microsoft.com/en-us/library/aa394084.aspx 를 참조하기 바란다.

Step 7. Step 6에서 획득한 Network Adapter들 중에서 IPEnabled(IP 변경 가능 속성)이 TRUE인 녀석의 Index를 찾는다.

Step 8. IP와 서브넷마스크의 값을 설정한다.

Step 9. Object Path를 설정한다.
여기서 Object Path에 대해서 설명하자면.. IP와 서브넷을 변경하기 위해 Win32_NetworkAdapterConfiguration 클래스에서 제공하는 MethodEnableStatic이다. 이 Method의 타겟이 바로 Object Path라고 할 수 있다. (EnableStatic의 보다 자세한 내용은 http://msdn2.microsoft.com/en-us/library/aa390383.aspx 를 참조하기 바람)

이 부분이 필요한 이유는 비록 내 PC에서 네트워크 환경에서 보이는 로컬 연결 속성이 하나라고 해서, Network Adapter가 1개가 아니고, 로컬 연결 속성으로 사용되지 못하기 때문에, 눈에 보이지 않는 Network Adapter가 다수 존재한다. 따라서, Step 7도 이러한 이유에서 이다.

결국, EnableStatic의 타켓은 Win32_NetWorkAdapterConfiguration.Index이고, Step 7에서는 이 Index를 찾기 위한 단계였다.

Step 10 ~ Step 14는 앞서 설정한 속성들을 Network Adapter에 반영하기 위한 단계들인데, 여기에 등장하는 함수들은 MSDN을 참고하기 바란다.

다음의 코드는 단순히 기능 구현에 중점을 뒀기 때문에, 코드 최적화에 대해서는 전혀 고려하지 않은 막장 코드이므로, 실제 응용을 위해서, 다듬을 필요가 있다. 

소스코드 다운로드: http://www.nohungry.net/Data/IPHandler.zip

크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 노헝그리

2007/11/20 22:20 2007/11/20 22:20
, , ,
Response
No Trackback , 2 Comments
RSS :
http://www.nohungry.net/tt1/rss/response/116

최근에 강좌란에 이와 관련한 내용이 없는 것 같아, 간단한 지식이지만 올립니다.

설치 및 배포 프로젝트는 간단히 말해서 Install Shields나 Install Factory같이 사용자를 위한 셋업 프로그램을 만들수 있도록 제공되는 기능입니다.

프로그래머는 이 설치 및 배포 프로젝트를 이용해 사용자가 보다 편리하게 프로그램을 설치할 수 있도록 도움을 줄 수 있습니다.

그럼, 설치 및 배포 프로젝트에 대해서 보다 상세하게 알아보도록 하겠습니다.

아래 그림과 같이 배포를 목적으로한 어떤 프로젝트가 있다고 가정해보겠습니다. 

우리는 이 프로젝트가 속한 솔루션에 설치 및 배포 프로젝트를 추가합니다.

프로젝트 추가에 성공하면, 우리는 솔루션 탐색기에 다음과 같이 설치 프로젝트가 추가된 것을 확인할 수 있습니다.

그럼 이제 이 설치 프로젝트에 우리가 배포하고자 하는 프로젝트를 추가합니다. 추가하는 방법은 다음과 같습니다.

설치 프로젝트(위에서는 Setup이란 이름의 프로젝트)를 선택한 상태에서 마우스 우클릭을 한 다음, 메뉴가 나타나면, 추가 - 프로젝트 출력을 선택합니다. 

다음과 같은 항목이 나타나면, 우리는 우리가 추가하고자 하는 프로젝트를 선택하고, 확인을 누릅니다.

창이 닫히고 나면, 설치 프로젝트 아래, 발견된 종속성에는 Microsoft.NET Framework이란 항목이 추가가 되어 있고, 프로젝트 아래에는 HelloWorld의 기본 출력(활성)이란 항목이 새로이 추가된 것을 확인할 수 있습니다.

이 때, 발견된 종속성에는 만약 배포하고자 하는 프로젝트에 .NET Framework에서 제공하는 참조(DLL 등) 이외에 추가적인 참조가 존재한다면, 자동적으로 포함이 됩니다. 하지만, 가끔 추가가 되지 않는 경우도 있는데, 이 때는 직접적으로 추가를 해야합니다. 

그럼 이제 속성 창을 살펴보도록 하겠습니다. 속성창의 항목들은 기본적으로 속성 이름을 통해 그 역할을 직관적으로 이해할 수 있습니다.

이 속성들 중에서 매우 중요한 2가지 항목을 꼽자면, 바로 RemovePreviousVersionVersion이 아닐까 싶습니다.

RemovePreviousVersion은 새로운 배포 버전을 설치할 때, 이전 버전의 프로그램을 제거하고 설치할 것인지를 설정하는 속성입니다. 이 때, 버전은 프로그램의 버전이 아닌, 셋업 프로그램의 버전을 보고 판단합니다.

따라서, 이전 셋업 프로그램의 Version이 1.0.0이었다면, 새로 배포할 때는 이 버전을 업그레이드 해줘야 합니다.

Version 항목의 값을 수정하면, 다음과 같은 창이 나타나는데, "예"를 선택합니다.

만약, "예"를 선택하지 않은 경우, 이전 버전을 제거하지 못하는 경우가 발생합니다.

 

그럼 이제, 파일 시스템 항목에 대해서 살펴보겠습니다.

일 시스템 항목은 우리가 배포하고자 하는 항목을을 사용자 시스템의 어느 곳에 위치시킬 것인지를 결정하는 속성이라 이해하면 됩니다.

예를 들어, 프로그램의 실행 파일은 응용 프로그램 폴더에 두고, 실행 파일의 바로 가기는 사용자 바탕화면에, 그리고, 도움말 등은 사용자 프로그램 메뉴에 추가한다는 식으로 말입니다.

설치 프로젝트에 우리가 배포하고자하는 프로젝트를 추가하면, 디폴트 값으로 응용 프로그램 폴더에 실행 파일이 추가됩니다.

만약, 우리가 이 실행 파일의 바로가기를 바탕화면에 추가하고 싶다면?

그림에서 HelloWorld의 기본 출력(활성)에서 마우스 우클릭을 한 다음, 바로 가기 추가를 선택하여 바로 가기를 만듭니다. 그리고 이 바로가기를 드래그 & 드롭을 이용해 사용자 바탕화면으로 이동시키면 됩니다.

이 때, 주의해야할 사항은 기본적으로 바로가기의 이름은 HelloWorld의 기본 출력(활성)의 바로가기란 다소 어색한 이름으로 만들어집니다. 만약, 이 상태로 설치 프로그램을 만들어, 설치하면 바탕화면에 이 어색한 이름 그대로 만들어지게 되는 것이죠.

그러므로 HelloWorld같이 바로가기의 이름을 수정하여 배포하는 것이 덜 어색하겠죠..^^.

아, 그리고 한가지 더.. 기본적으로 바로가기의 속성창에 보면 Icon 속성에 '없음'이라고 되어있습니다.

이 상태로 배포하면 당연 바탕화면의 바로 가기는 아무런 아이콘이 없는.. (엄밀히 말하면 도스 창 형태의 아이콘을..) 상태로 사용자 바탕화면에 추가되게 됩니다. 그다지 보기 좋지 않겠죠..^^

여기까지 하셨다면, 가장 기본적인 인스톨 프로그램을 완성하실 수 있게된 것입니다.

하지만, 아직 부족한 점이 몇 몇 보입니다. 예를 들어, 고객의 정보를 입력 받는 창을 만들고 싶다던지, 프로그램이 설치되고 나면, 라이센스(EULA)에 관한 텍스트 파일을 보여준다던지, 회사의 홈페이지가 나타나게 하고 싶은데 말입니다.

이와 같은 내용은 다음 강좌에서 설명할 수 있도록 하겠습니다. 아울러, 이 설치 프로젝트를 보다 커스터마이징할 수 있는 Installer 클래스에 대해서도 알아보도록 하겠습니다.

- 이상 데브피아 강좌란에 내가 썼던 글-ㅁ-;

크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 노헝그리

2007/10/11 12:34 2007/10/11 12:34

저도 특정 테이블에서 데이터를 가져오는 것이 아니라, 데이터를 재가공한 후, 크리스탈 레포트로 출력하는 형식이었는데,

다음과 같이 진행하였습니다..^^

우선 님이 크리스탈 레포트에 출력하고자 하는 형식의 데이터셋 파일(*.xsd)을 만드세요. 그러면 원래 마법사가 뜨면서 Connection String도 넣어라고 하고, 나오죠? 거기서 취소를 하고 도구상자에서 DataTable을 하나 끌어와서 만듭니다.

그 DataTable을 임의로 MyTable이라고 하기로 하죠.
그리고 ID랑 Name이란 2개의 칼럼을 만들었다고 가정하겠습니다..^^ 그리고 저장을 합니다.

그럼 이 xsd 파일은 크리스탈 리포트 형식(*.rpt) 파일의 기반이 됩니다.
그러면, CrystalReportSource와 CrystalReportViewer를 각각 생성하고, cs와 cv라고 명명했다고 하죠.

그럼 rpt파일은 xsd파일을 이용해서 생성된 것이고, cs는 이 rpt파일을 기반으로 생성됩니다. 이해가 되시나요?^^;;

cv의 보고서 소스는 바로 cs를 선택하시면 되겠죠.. 그럼.. 크리스털리포트뷰어에 ID와 Name으로 구성된 페이지가 나올겁니다..

그럼 이제 내용을 채워야겠죠.. 내용을 채우는 순서는 다음과 같습니다.

1. DataTable 타입의 객체를 CrystalReportSource에 바인딩시킨다.
2. CrystalReportViewer의 ReportSource에 CrystalReportSource를 할당한다.
3. 그리고 CrystralReportViewer를 Refresh한다.

그럼 먼저 DataTable 객체를 선언하고, 정의해보면..

DataTable dataSrc = new DataTable();

dataSrc.Columns.Add("ID");
dataSrc.Columns.Add("Name");

dataSrc.Rows.Add(new string[]{"23", "Michael Jordan"});
dataSrc.Rows.Add(new string[]{"10", "Pele"});

이렇게 하시면 됩니다..^^

그럼 이제 이 객체를 CrystalReportSource에 바인딩시켜야겠죠.
아까 CrystalReportSource를 생성하고, 이름을 cs로 했다고 했으니...

cs.ReportDocument.SetDataSource(dataSrc);
cs.DataBind();

하면 됩니다.. 그리고 CrystalReportViewer의 ReportSource에 cs를 할당하고, 보고서를 새로 그려주면 됩니다.

cv.ReportSource = cs;
cv.RefreshReport();

-끝-

너무 길게 그리고.. 두서없이 쓴 것 같네요..^^; 그럼 즐프하세요.

-------------------------------------------------------------------------------------------
내가 예전에 데브피아에 쓴 답글..
근데, 시간이 흘러.. 갑자기 나도 써야하니.. 기억이 안나서 찾는다고 고생했다..
그래서 내 블로그에 남겨둠..-_- 이 한심한 기억력이란.. 쯧-ㅁ-

크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 노헝그리

2007/10/02 17:24 2007/10/02 17:24
, ,
Response
55 Trackbacks , 3 Comments
RSS :
http://www.nohungry.net/tt1/rss/response/104


예전에도 아티클을 올린 적이 있었지만, DirectShow Programming을 Visual Studio 6.0에서 구현한다는 것은 상당히 번거로운 일이다.

MS에서 Visual Studio 6.0을 내놓은 자식 취급하면서 찾아온 일이지만.. 갠적으로 C++ 프로그래밍은 Visual Studio 6.0으로 해야 제 맛이라 생각하는 나에겐 여간 껄쩍찌근한게 아니다.

우습게도 C#때문에 Visual Studio 2005가 상당히 손에 익었음에도 C++ 만큼은 손에 익지 않는다. 문자열들 간의 타입 캐스팅이 까다롭다는 것은 사실 둘째 치고라도, 배경화면을 까맣게 맹글어놓고 쓰는 나에게 2005는 화면을 까맣게 맹글어도 영 아니 이쁘다는 것도 짜증난다-_-

암튼, 예전에 회사일 때문에 Visual Studio 6.0으로 DirectShow를 이용한 프로그램을 구현하다가 갑자기 일이 Drop 된 경우가 있었는데.. 이번에 도현이형의 부탁도 있고, 나도 예전에 하던걸 마무리 지어야 된다는 생각에서 프로그램을 마물했다.

혹시나 다음에도 DirectShow로 프로그래밍해야할지도 모를 기억력이 부족한 날 위해 몇 몇 중요 뽀인뜨를 기록하고자 한다.

1. DirectShow SDK는 반드시 2003년에 배포된 버전을 사용하자. 갠적으로 2월에 배포된걸 썼는데, 아무 문제가 없었다. (그 이후에서는 MS가 더이상 6.0을 내놓은 자식 취급하면서 전혀 고려하지 않고 있다.)

2. 만약, h파일들을 찾을 수 없다는 에러 메시지가 나타난다면?! DXSDK 설치 폴더 아래 Sample/VC++/BaseClasses 경로를 Include 경로에 추가해주자.

3. 반드시 다음 lib 파일들을 순서대로 링크시켜주자! strmiids.lib winmm.lib strmbase.lib quartz.lib
만약, Debug 모드라면 strmbase.lib -> strmbased.lib 로 고쳐주어야 하고, 반드시 Link Incremetally를 체크해주자!
만약, strmiids.lib와 strmbase.lib의 순서가 바뀌면, 중복 정의되었다는 에러메시지를 뱉어낸다.


덧글) 막상 DirectShow로 구현하고 나서, DirectShow SDK에서 제공하는 샘플들을 몇 개 돌려봤다. 그 중 AmCap이란 녀석과 PlayCap이란 녀석 2개가 있었는데.. 영상에 대한 반응속도.. 그러니까 카메라에 대고 손을 흔들었을 때의 반응을 보니, AmCap이 PlayCap보다 더 빠른 것 같았다. 왜 그럴까에 대해서.. 정말 알아보고 싶었지만, 시간 관계상 일단 접었다.. 다음에 기회가 되면 꼭 소스를 분석해봐야겠다..-ㅁ-
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 노헝그리

2007/08/17 14:47 2007/08/17 14:47
Response
55 Trackbacks , No Comment
RSS :
http://www.nohungry.net/tt1/rss/response/99

소프트웨어 디자인 패턴에 대해 공부하기 위해 웹을 헤매던 중.. Exception Handling에 대한 내용을 다룬 Article을 읽었다. 거기에 소개된 내용이 바로 RAII란 개념이다.

쉽게 얘기하면, Stack-based 변수Heap-based 변수와 관련 있는 얘기다.
다음과 같은 코드를 생각해보자.
<Example #1>
CSomething something("Stack");                                 // Stack-based 변수
CSomething* pSomething = new CSomething("Heap");   // Heap-based 변수

// 생략 ...

delete pSomething;
pSomething = NULL;

<Example#1>에서 알 수 있듯이, Stack-based 변수는 소멸자 해제를 Runtime이 관리해주고, Heap-based 변수는 프로그래머 자신이 관리해야된다. (다 아는 얘기지만.. new를 했으면, delete를 해줘야 하는 법...)

이걸 깜빡하면, 결국 메모리 누수(Memory Leak)이란 재앙을 만나게 된다.

근데, 이렇게 다 아는 얘기를 왜?! 하고 싶은 얘기는 지금 부터다.
학교 숙제를 할 때 우리는 예외 처리(Exception Handling)에 대한 중요성을 소홀히 할 때가 많다.
물론, 조환규 교수님께서는 늘 프로그램의 가장 중요한 덕목은 땐땐함(Robust)이라고 하셨지만..ㅎ 숙제 마감에 시달리게 되다보면, 그걸 지키지 못하는 경우가 허다하다.

<Example #1>을 다음과 같이 수정해보자.
<Example #2>
CSomething something("Stack");                                 // Stack-based 변수
CSomething* pSomething = new CSomething("Heap");   // Heap-based 변수

try{
// 생략 ...
}
catch(int exception_code)
{
     cout << "Exception Occured." << endl;
     delete pSomething;
     pSomething = NULL;
}

delete pSomething;
pSomething = NULL;

자, 예외 처리가 들어가면서, 코드가 뒤죽박죽이 되어버렸다. 동일한 코드가 반복적으로 사용되었고, 예외처리 부분과 자료구조 부분도 섞여버렸다. 이런 부분이 꼭 나중에 문제를 일으키기 쉽다.

깜빡하고, delete를 안해줘서 메모리 누수가 발생하거나, 아니면, 나중에 코드를 유지보수해야할 때도 골치아프게 된다.

이렇게, 골치가 아프게 되는 원인은, Heap-based 변수에 있다. Heap-based 변수는 바로 프로그래머가 관리해줘야 하기 때문이다. 그래서 가급적이면 Heap-based 변수를 사용하지 말자. (포인터를 쓰지 않겠다는 말이냐고?!)

당근, 그건 아니다. 그래서, 필요한 것이 바로 Smart Pointer~!
다음과 같은 코드를 만들어보자.
<Example #3>
class CSomethingPtr
{
public:
CSomethingPtr(CSomething* pSomething);
~CSomethingPtr();

private:
CSomething* m_pSomething;
};

CSomethingPtr::CSomethingPtr(CSomething* pSomething)
: m_pSomething(pSomething)
{
}

CSomethingPtr::~CSomethingPtr()
{
delete pSomething;
pSomething = NULL;
}

그럼, <Example #3>를 이용해 <Example #2>를 수정해보자.
<Example #4>
CSomething something("Stack");                                           // Stack-based 변수
CSomethingPtr pSomethingPtr(new CSomething("Stack"));       // Stack-based 변수

try{
// 생략 ...
}
catch(int exception_code)
{
     cout << "Exception." << endl;
}

이런 식의 기법을 바로 Smart Pointer(포인터처럼 동작하는 객체)라고 한다.
바로 지역객체(Stack-based 변수)를 사용하여 자원을 관리한다고 해서 이를 RAII라고 한다.

RAII에 대해서 공부하면서, 문득 생각난.. 왜 DirectShow SDK에서 Pointer 대신 CComPtr과 같은 형식의 클래스가 많은지 이제 깨달았다. (그 때는 별 생각없이 썼는데.. 돌이켜보면 바로 이런 관점에서 작성한 것이었으리라..)
아무튼, 앞으로도 이런 내용을 보다 열심히 공부할 필요가 있겠다.


보다 자세한 내용은 고형호님의 블로그(http://www.innosigma.com)에 가시면 찾아볼 수 있습니다..^^

크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 노헝그리

2007/07/04 11:42 2007/07/04 11:42
Response
No Trackback , 2 Comments
RSS :
http://www.nohungry.net/tt1/rss/response/92


회사에서 다가올 프로젝트에 쓰여질 그래프 라이브러리를 선택하기 위해, 여러 그래프 라이브러리를 테스트하던 중, 그 중 ChartFX ClientServer 6.2 버전도 포함되어 있었다.

ChartFX ClientServer 6.2는 Visual Studio 6.0을 지원한다고 되어 있었지만.. 어처구니 없게도 샘플 프로그램이라던지.. User Reference Guide에서도 C#과 VB에 대해서만 설명이 되어있을뿐 구할 수가 없었다.

그래서 몸소 삽질해서 그 방법을 체득하는 수 밖에 없었다.

Step 1. 우선 ChartFX ClientServer 6.2를 설치한다.
Step 2. Visual Studio 6.0에서 임의의 프로젝트를 생성한다. (아래 예제에서는 Dialog Base로 만들었다.)
Step 3. 마우스 오른쪽 버튼을 눌러서, Insert ActiveX Control... 을 누른다.


Step 4. Chart Object를 선택하고, OK 버튼을 누른다.


Step 5. 그럼, 아래 그림과 같이 Chart Object가 삽입되었음을 확인할 수 있다.

Step 6. Class Wizard를 통해 삽입된 Chart Object에 변수를 할당(Add Variables)하고자 하면, 다음과 같은 메시지가 나타나게 된다.


Chart Object가 삽입되었는데.. 이 녀석을 제어하기 위해 C++ Wrapper Class를 만들 것이냐고 묻는 내용이다. 확인을 선택한다.

Step 7. 그러면, 다수의 헤더(.h) 파일과 소스(.cpp) 파일들이 생성될 것이라 보여준다. 클래스 이름과 헤더 파일 이름, 소스 파일 이름은 자신의 구미에 맞게 설정할 수 있다.

Step 8.
아래와 같이 Wrapper Class가 생성된 것을 확인할 수 있다.

이 Wrapper Class를 어떻게 사용하였는지는 첨부된 샘플 코드를 통해 분석하기 바란다.














덧붙이는 글
1. 삽입된 Chart Object에서 마우스 오른쪽 버튼을 클릭하여, properties를 실행하면, 그래프의 여러가지 속성들을 설정할 수 있다. 그 중에 우리가 특히 눈여겨 보아야할 속성들은 다음과 같다.

Gallery : 그래프의 모양에 관한 속성이다. (Bar, Line, Pie 등 십수가지의 그래프 형태가 지원된다.)
NSeries: 서브 그래프의 개수에 관한 속성이다.
NValues: 그래프의 데이터 개수에 관한 속성이다.

나머지 속성들은 한 번씩 바꿔보고, 변화되는 것을 보면 알 수 있다.

2. 함수들의 쓰임새는 대략 C#이나 VB용 Reference Guide를 보면 알 수 있다. 그러나 제일 곤혹스러운 것은 COD_VALUES나 COD_REALTIME같은 미리 정의된 상수들의 값을 알 수 없다는 사실이다. C#이나 VB에서는 이 녀석들을 enum 타입으로 정의한 것 같은데, C++에서는 함수의 파라미터로 long 타입을 받아, 결국 이 enum 타입을 알아내기 위해 C# 프로그램에서 다음과 같은 방법을 써서 알아냈다.

MessageBox.Show(Convert.ToInt32(COD.COD_AddPoints).ToString());

덧붙여, 필요에 의해 내가 알아낸 enum 타입들을 다음과 같이 재정의해서 사용하였다.
#define COD_VALUES 1
#define COD_REALTIME 16
#define COD_ADDPOINTS 128
#define COD_ALLOCHIDDEN 512
#define COD_REMOVE 2048
#define COD_SCROLL_REGEND 8192

#define CHART_TYPE_NOLEGINVALIDATE 8

#define REALTIMESETTING_STYLE_LOOPPOS 1
#define REALTIMESETTING_STYLE_NOWAITARROW 2

샘플프로그램 다운로드 - 귀차니즘에 의해, 주석이 별로 없지만.. 이해하시는데는 큰 무리가 없을 겁니다. 그리고, Trail 버전으로 테스트한 것이라 배포가 불가능하여, 샘플 프로그램 자체는 실행되지 않습니다. 단지, 코드 참조만으로 사용하시기 바랍니다.

ChartFX에 대한 보다 많은 정보:
http://www.softwarefx.co.kr

크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 노헝그리

2007/06/28 10:49 2007/06/28 10:49
, , ,
Response
73 Trackbacks , 4 Comments
RSS :
http://www.nohungry.net/tt1/rss/response/90