블로그 이미지
대갈장군

calendar

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 31

Notice

2009. 12. 19. 05:50 프로그래밍
C++이나 C#은 매우 크고 방대한 언어다. 문법도 많고 외워야 할 것도 많으며 규칙도 정말 많다. 책을 사서 1장 부터 읽다보면 3장쯤 가면 복잡해지기 시작하면서 뭐가 뭔 말인지 모르겠다... @.@ 한숨을 푹쉬고 책을 덮는다... 그리고 속으로 '더 쉬운책이 없을까?' 라고 생각한다.

내가 많이 겪은 경험이다. 이것은 책이 자습서로서의 역활을 못하고 있다는 말과 같다. 거대한 개념이 있다면 그것의 핵심에 접근하기 위해서는 부분 부분이 아닌 전체의 맥과 흐름을 집어주는 역활을 자습서는 반드시 해야 한다.

내가 읽어본 많은 책들은 그렇지 못했지만 유일하게 김상형님이 쓰신 모든 저서는 이 흐름을 잡아준다. C++, C#이라는 거대한 것을 하나하나 분리해 서로를 유연하게 연결한 다음 독자가 충분히 어떤것을 이해할 단계에 도착하면 거기서 거대한 전체 지도를 보여주면서 내가 왜 여기에 왔는지 그리고 앞으로 어떤 길을 가야 하는지 정확하게 알려준다.

김상형님의 책을 보면서 깨우친 것을 나름대로 정리하고자 하는데 그 첫째가 바로 객체 지향의 기본인 '클래스'이다.

가장 단순하게 클래스를 정의하면 C 구조체의 확장형태라고 생각할 수 있다. 그냥 뭐 이런 저런 변수를 담는 통으로 생각하기 쉽다.

하지만 C#에 들어오면서 완전 객체 지향성을 강조하게 되면서 구조체와 클래스는 '상속'이라는 결정적 차이를 가지게 된다. 바로 이 상속이 가능해 지면서 클래스는 '계층'이라는 말에 더 가까워 졌다.

상속인터페이스를 이용한 뚜렷하고 명확한 계층 구조의 클래스 설계로 한눈에 들어오는 구조적 설계가 가능해 졌다. 바로 이것이 객체 지향 프로그래밍의 핵심이다. (인터페이스는 차후 설명하겠다.)

예전에도 언급했듯이 이제는 프로그램 개발자가 두 부류로 분류가 된다. 첫째는 라이브러리 개발자다. 대형 회사, 즉, microsoft와 같은 회사에서 최종 사용자가 사용할 수많은 라이브러리 함수와 클래스를 만들어내는 사람을 말한다. 둘째는 최종 개발자다. 이 사람은 나와 같은 사람으로 대형 회사 개발자가 만들어 놓은 수많은 라이브러리 함수를 불러와 사용하기만 한다. 

고로 나와 같은 최종 개발자들은 내가 쓸 함수를 처음부터 일일이 만들어 쓰는게 아니라 '잘 불러다가' 쓰면 그만이다.

바로 이 '잘 불러다가'가 '구조 설계'이며 이 '구조 설계'를 위해 가장 사람에게 직관적이고 적합한 분류 방식이 계단식 방식, 이른바 'Class (계급 혹은 계층) 구조' 이다. 

내가 판단하기로는 클래스의 의미가 바로 여기서 나왔다고 생각하지만 물론 아닐 수도 있다. ㅋㅋㅋ (아님 말고)

상속은 부모 클래스의 모든 것을 재사용하며 동시에 추가적인 것을 곁들여 새로운 자식 클래스를 만들어내는데,  이것은 계층적 구조 설계에 딱 맞아 떨어지는 방식이다. 

클래스를 문법적으로 설명하자면, 생성자, 파괴자, 가상함수, 추상함수, 멤버 변수, 정적변수, 정적클래스, 봉인클래스, 순수 가상함수, 추상클래스 등등등등 수많은 것들이 존재하지만, 내가 이 글에서 말하고자 하는 것은 클래스라는 단어가 객체 지향 언어에서 선택 되었는가이다. 

거대한 객체 지향 언어를 한 두발 떨어져서 그 의미와 구조, 근원을 볼 수 있게 되면 세세한 문법과 규칙들이 너무나도 당연하게 받아들여지는 순간이 있다. 내가 원하는 것은 바로 그것이다.





posted by 대갈장군
2009. 11. 24. 00:20 나의 이야기
무한도전에 대해 말이 많다. 우선 정준하에 대한 논란인데 이건 그의 설정이건 아니건 간에 정준하가 잘못했다. 무한도전을 웃고 즐기기위해 보는 것이지 아이리스처럼 스릴감을 느끼기 위해서 보는게 아니다. 보는 내내 내 마음이 불편하고 불안했다. 아무튼 김태호 PD의 말처럼 시청자가 불편을 느겼다면 그것은 분명 편집을 완벽하게 하지 못한 무한도전의 잘못이다.

이 논란외에 타블로 형의 무한도전 '비난' 논란이 일어났는데 이 부분에 대해서는 좀 할말이 많다. 우선 내가 그 사람의 생각을 '비난'이라고 정의한다는 점이 중요하다. 

자신의 생각, 즉 의견을 전달하기 위해서는 첫째로 욕을 해서는 안된다. 욕이 들어가게 되면 설득력이 떨어진다. 내가 이성적이고 논리적인 의견을 펼치게 되면 비록 나의 의견에 동의하지 않는 사람이라고 할지라도 일단 '이해'는 하게 되지만 감정적으로 욕을 쓰게 되면 나의 의견에 대해서도 '감정적'인 리플이 돌아오게 마련이다.

결국 타블로의 형은 감정적인 자신의 생각을 썼으므로 그것은 '비판'이라기 보다 '비난'에 가깝다. 결국 그 글에 달리는 리플들도 감정적일수 밖에 없으며 그것은 '악플'이라기보다 감정적인 리플, 억지로 줄여 말하면 '감플'정도라고 할 수 있겠다. 

둘째로 그의 글에서 욕을 정화시키고 그의 논리만을 본다고 하더라도 별로 설득력이 없다. 우선 미국은 지역적으로 매우 큰 나라다. 한국처럼 지역적으로 작은 나라도 각 지역마다 특색이 있듯이 미국도 각 주와 도시별로 특색이 매우 다르다.

내가 살고 있는 도시는 매우 시골스럽다. 시골스럽다는 의미는 일단 도시가 작고 사람들이 여유로우며 눈만 마주쳐도 웃으며 인사한다는 의미다. 차를 타고 나가보면 길위에서는 양보의 미덕이 펼쳐진다. 빌딩에 들어가는 입구에서는 앞선 사람이 뒷 사람을 위해 문은 열어주고 서로 'Thank you'와 'You're welcome'이 남발한다.

하지만 점점 큰 도시로 나갈 수록 서울과 같은 느낌이 들기 시작한다. 길위에서는 경적을 울리는 소리가 여기저기서나고 지나가는 사람들은 서로 눈을 안마주치며 쌩쌩 지나다닌다. 여유로움이 없으며 자신의 할 일에만 몰두한다.

뉴욕은 어떠한가? 그곳은 말그대로 세계에서 가장 바쁘고 가장 큰 도시중 하나다. 그런 곳에서 얼마만큼의 여유로움을 뉴욕커에게서 바라는가? 피자집 종업원이 박명수와 길이 영어를 못하는 동양인이라서 무시했다고 생각했다면 큰 오산이다. 단지 그 이유만으로 무시했다고 보는 것 보다는 여러가지 다른 이유가 있다고 본다. 우선 무턱대고 카메라를 들이댔다는 점이 프라이버시를 중요시하는 미국정서에 반하고 점심시간처럼 바쁜 타임에 어물정거리며 주문은 안하고 웃기만 하는 그들이 점원 입장에서는 '영양가는 없고 시간만 낭비하는 손님'으로 보였을 것이다. 이것을 보고 타블로의 형은 아마도 자신이 받은 '피해의식'과 결합을 했던 것 같은데 이것은 섣부른 판단이다.

나 역시 미국에 와서 살고 있다. 나 또한 많은 경험을 해보았다. 하지만 중요한 것은 내가 영어를 못하는 아시아인이라서 부당한 대우를 받은 것이 아니라 내가 말을 하는 상대방의 기분과 성격 그리고 미국의 문화와 정서를 이해하지 못했기 때문에 무시를 받은적이 대부분이다. 하지만 나는 그것을 '영어못하는 아시아인'이라서라고 자기 합리화하지 않았으며 다음부터는 이런일이 없도록 해야 겠다는 생각을 했을 뿐이다. 

무한도전에도 나왔지만 뉴욕의 친절한 사람들도 많이 나오지 않았는가? 결국 '영어 못하는 아시아인'이라서 무시받았다라고 생각하는 것은 자기 스스로의 피해의식에 근거한 것이며 이것을 반복하여 자신에게 되새기게 되면 모든 상황이 '영어 못하는 아시아인이라서...'로 귀결되게 된다. 앞뒤 상황을 고려하지 않은채 오직 제한된 상황을 근거로 자신의 추측만 늘어놓은 그의 비난은 설득력이 없다. 

무한도전 역시 모든 부분에서 잘한 것은 아니다. 하지만 그들이 노력은 늘 높게 평가한다. 미국에 와서 일본식 식당을 가면 늘 한국 음식 생각을 하며 '한국음식 팔면 참 장사 잘된텐데...'라고 생각한 적이 한 두번이 아니다. 실천하는 무한도전의 용기는 언제나 아름답다.

기본적으로 나라를 사랑하고 타인을 배려할줄 아는 사람이라면 단점에 대한 '욕'보다는 장점에 대한 '칭찬'을 먼저 하는 것이 발전을 위한 보다나은 방향이라고 생각한다. 


'나의 이야기' 카테고리의 다른 글

Alaska  (0) 2010.02.18
기도  (2) 2010.02.03
노무현 대통령 타살 의혹  (0) 2009.05.27
공간 이동  (0) 2009.03.12
친구 이야기  (2) 2008.12.12
posted by 대갈장군
2009. 11. 21. 06:35 카테고리 없음
네필 대함방에서 15만 어택하고 터진 대박 경험치... 후아... 유료 계정도 아닌 무료 계정에서 터진 경험치로는 최대치인것 같음... 
posted by 대갈장군
2009. 11. 17. 05:01 프로그래밍/Windows API
차일드 윈도우는 자식 윈도우다. 차일드 윈도우를 생성할때는 CreatWindow() 함수에서 3번째 인수값으로 WS_CHILD 플래그를 넣고 8번째 인자에 부모 윈도우의 핸들을 주면 된다. 

고로 상식적으로 부모 윈도우에 딸린 것이 차일드 윈도우이므로 부모 윈도우 내부 영역에서만 차일드 윈도우는 유효하다. 차일드 윈도우도 윈도우 이므로 임의의 WndProc 함수를 가질수 있다. 고로 독립적인 행동이 가능하다. 

차일드 윈도우는 부모가 파괴될 때 자동으로 같이 파괴되므로 WM_DESTROY에 대한 처리가 필요없다. 행여나 처리를 해서도 안된다. 

팝업 윈도우는 차일드와는 달리 부모 윈도우의 작업 영역을 벗어날 수 있고 부모 윈도우 이동시에도 자신의 위치를 고수한다. (차일드의 경우는 부모 윈도우와 같이 움직인다.) 

'프로그래밍 > Windows API' 카테고리의 다른 글

윈도우 메모리 - 2 (malloc 함수)  (2) 2011.03.11
윈도우 메모리 - 1  (0) 2011.03.10
윈도우 - SetClassLongPtr(), SetWindowLongPtr()  (0) 2009.11.17
윈도우 - WNDCLASS 구조체  (0) 2009.11.17
윈도우 - CreateWindow()  (0) 2009.11.17
posted by 대갈장군
2009. 11. 17. 04:50 프로그래밍/Windows API
윈도우 클래스 와 윈도우는 실행 중에도 그 속성을 변경할 수 있다. 다시 말해서 윈도우 클래스에서 설정했던 각종 속성을 실행중 변경가능 하다는 말이다. 이것이 대단한 이유는 서브클래싱이라는 기법을 가능하게 해주기 때문이다.

서브 클래싱이란 윈도우마다 설정되어 있는 동작 함수인 WndProc를 실행중에 교체함으로써 전혀 다른 동작을 할수 있게 만들어주는 기법이다. 

아무튼, 총 8가지의 윈도우 클래스 / 윈도우 속성 설정 함수가 있으나 64비트 운영체제가 도입된 이후로는 기왕이면 Ptr이 붙은 64 비트용 함수를 사용하는 것이 범용성 면에서 유리하다.

윈도우 클래스 속성 설정 함수는 (WNDCLASS 변경) GetClassLongPtr()과 SetClassLongPtr() 이고, 윈도우 속성 설정 함수는 GetWindowLongPtr()과 SetWindowLongPtr() 함수다. 여기서 윈도우 프로시져 함수의 주소를 바꾸고 싶다면 GWLP_WNDPROC를 인수로 넣으면 된다. 

주의 할 것은 스타일이 플래그 형식으로 비트의 On/Off에 의해서 판단하므로 대입연산이 아니라 & 또는 | 연산으로 플래그를 설정해야 한다는 점이다.


'프로그래밍 > Windows API' 카테고리의 다른 글

윈도우 메모리 - 1  (0) 2011.03.10
윈도우 - 차일드, 팝업  (0) 2009.11.17
윈도우 - WNDCLASS 구조체  (0) 2009.11.17
윈도우 - CreateWindow()  (0) 2009.11.17
메모리, Win32 vs. Win16  (2) 2009.05.22
posted by 대갈장군
2009. 11. 17. 03:34 프로그래밍/Windows API
CreateWindow() 함수를 사용하여 응용 프로그램 로컬 윈도우 클래스를 생성하고자 한다면 WNDCLASS 구조체를 채워넣어야 한다.

typedef struct {
    UINT style;
    WNDPROC lpfnWndProc;
    int cbClsExtra;
    int cbWndExtra;
    HINSTANCE hInstance;
    HICON hIcon;
    HCURSOR hCursor;
    HBRUSH hbrBackground;
    LPCTSTR lpszMenuName;
    LPCTSTR lpszClassName;
} WNDCLASS, *PWNDCLASS;

이 구조체 중에서 중요한 3가지는 lpszClassName, lpfnWndProc, 그리고 hInstance 요소로서 이 세놈은 기본값이 없으므로 생략할 수 없다. 

lpszClassName이 바로 CreatWindow() 함수의 첫번째 인자가 될 것이므로 되도록이면 만들고자 하는 윈도우를 잘 나타내는 이름을 지어주자. 

hInstance는 이 윈도우 클래스를 등록한 응용 프로그램의 인스턴스 핸들이다. 여기서 지정된 응용프로그램이 종료되면 윈도우 클래스도 같이 파괴된다. 주로 WinMain 으로 전달된 hInstance 인수를 그대로 사용하면 된다.

마지막으로 lpfnWndProc는 메시지 처리 함수다. 뭐, 이놈이 사실 내가 만드는 윈도우의 모든 동작을 정의한다. 

이 외에 style 인자가 재미 있는 녀석인데 윈도우의 스타일을 지정하는 인수다. 지정할 수 있는 것들로는 
StyleAction
CS_BYTEALIGNCLIENT Aligns the window's client area on a byte boundary (in the x direction). This style affects the width of the window and its horizontal placement on the display.
CS_BYTEALIGNWINDOW Aligns the window on a byte boundary (in the x direction). This style affects the width of the window and its horizontal placement on the display.
CS_CLASSDC Allocates one device context to be shared by all windows in the class. Because window classes are process specific, it is possible for multiple threads of an application to create a window of the same class. It is also possible for the threads to attempt to use the device context simultaneously. When this happens, the system allows only one thread to successfully finish its drawing operation.
CS_DBLCLKS Sends a double-click message to the window procedure when the user double-clicks the mouse while the cursor is within a window belonging to the class.
CS_DROPSHADOW Windows XP: Enables the drop shadow effect on a window. The effect is turned on and off through SPI_SETDROPSHADOW. Typically, this is enabled for small, short-lived windows such as menus to emphasize their Z order relationship to other windows.
CS_GLOBALCLASS Specifies that the window class is an application global class. For more information, see Application Global Classes.
CS_HREDRAW Redraws the entire window if a movement or size adjustment changes the width of the client area.
CS_NOCLOSE Disables Close on the window menu.
CS_OWNDC Allocates a unique device context for each window in the class.
CS_PARENTDC Sets the clipping rectangle of the child window to that of the parent window so that the child can draw on the parent. A window with the CS_PARENTDC style bit receives a regular device context from the system's cache of device contexts. It does not give the child the parent's device context or device context settings. Specifying CS_PARENTDC enhances an application's performance.
CS_SAVEBITS Saves, as a bitmap, the portion of the screen image obscured by a window of this class. When the window is removed, the system uses the saved bitmap to restore the screen image, including other windows that were obscured. Therefore, the system does not send WM_PAINT messages to windows that were obscured if the memory used by the bitmap has not been discarded and if other screen actions have not invalidated the stored image.

This style is useful for small windows (for example, menus or dialog boxes) that are displayed briefly and then removed before other screen activity takes place. This style increases the time required to display the window, because the system must first allocate memory to store the bitmap.

CS_VREDRAW Redraws the entire window if a movement or size adjustment changes the height of the client area.

여기서 주의해서 볼 필요가 있는 속성 두가지는 CS_DBLCLKS와 CS_NOCLOSE인데 첫번째 놈을 설정하지 않으면 마우스 더블클릭은 무시된다. (WndProc 함수로 전달되지 않는다는 말) 그리고 두번째 놈은 종료 버튼이 없도록 만든다. 심지어 Alt+F4도 안된다. 이 플래그가 설정된 경우 윈도우를 닫기 위해서는 반드시 다른 형태의 종료 방법이 제공되야 한다.


posted by 대갈장군
2009. 11. 17. 02:44 프로그래밍/Windows API
윈도우는 CreateWindow() 함수에 의해 만들어진다. 
HWND CreateWindow(      
    LPCTSTR lpClassName,     LPCTSTR lpWindowName,     DWORD dwStyle,     int x,     int y,     int nWidth,     int nHeight,     HWND hWndParent,     HMENU hMenu,     HINSTANCE hInstance,     LPVOID lpParam );
윈도우 역시 클래스로 부터 만들어지는데 이른바 '윈도우 클래스' 중 하나로 부터 만들어진다. 첫번째 인자 lpClassName은 바로 그 '윈도우 클래스'를 지칭하는 인자이다.

재미 있는 것은 MSDN에도 나와 있듯이, 
lpClassName
[in] Pointer to a null-terminated string or a class atom created by a previous call to the RegisterClass or RegisterClassEx function. The atom must be in the low-order word of lpClassName; the high-order word must be zero. IflpClassName is a string, it specifies the window class name. The class name can be any name registered with RegisterClass or RegisterClassEx, provided that the module that registers the class is also the module that creates the window. The class name can also be any of the predefined system class names. For a list of system class names, see the Remarks section.
이 첫번째 인자에 올수 있는 놈은 Null-Terminated String 혹은 A Class Atom (클래스 부류) 라고 했는데 이 놈들은 RegisterClass 함수나 RegisterClassEx 함수에 의해서 미리 (이전에) 등록되어진 놈이라고 한다.

윈도우 클래스를 크게 두가지 종류로 나누자면 시스템 (운영체제)에서 제공하는 기본 윈도우 클래스와 사용자가 정의해서 사용하는 사용자 윈도우 클래스가 있다.

운영체제가 제공하는 윈도우는 우리가 자주 사용하는 "button" "edit" 과 같은 놈들이고 사용자가 정의하는 윈도우는 WNDCLASS 구조체를 사용자가 원하는 윈도우 형태로 채워넣은 다음 RegisterClass 함수를 이용해서 등록한 후 사용하는 것을 말한다. 

그래서 내가 원하는 형태의 윈도우를 그리고 싶다면,
1. 우선 WNDCLASS 구조체의 각 요소를 내가 원하는 옵션으로 설정한다.
2. RegisterClass 함수를 이용해서 생성한 WNDCLASS 구조체를 등록한다.
3. CreateWindow 함수의 첫번째 인자에 내가 작성한 WNDCLASS 의 이름을 넣어준다. 

조금 복잡하더라도 이렇게 함으로써 사용자는 같은 형태의 윈도우를 쉽게 재생성 할 수 있다. (그것이 WNDCLASS를 생성하고 등록하는 이유)

윈도우 클래스는 범위로 분류하자면 시스템 전역 클래스, 응용 프로그램 전역 클래스 그리고 응용 프로그램 로컬 클래스로 나뉜다.

시스템 전역 클래스는 운영체제가 제공하는 윈도우 클래스들로 부팅하면 자동으로 등록되는 놈이다. 이것들이 바로 기본으로 제공되는 놈들로 button, edit, scrollbar, listbox 등이다.

응용 프로그램 전역 클래스는 주로 DLL에 의해 등록되며 이 DLL을 불러들인 프로세스에서 자유롭게 사용된다. 이것들의 예로는 프로그래스, 트리뷰, 리스트뷰 등이 있다. 의외로 이런 것들이 운영체제에서 제공되는 시스템 전역 클래스가 아니라는 점이다. 고로 윈도우의 버전과 종류에 따라 저런 부분의 구현이나 기능, 색상등이 달라지는 것이다. (DLL의 버전이 다르니까)

마지막으로 응용 프로그램 로컬 클래스는 사용자가 WNDCLASS를 정의하고 RegisterClass 함수로 등록하여 사용하는 윈도우 클래스를 말한다. 중요한 점은 클래스 이름이 중복될 경우 가장 먼저 로컬 클래스 부터 선택하고 그다음이 응용 프로그램 전역 클래스 그리고 마지막이 시스템 전역 클래스이다. 뭐, DLL과 검색 순위가 동일하다만. :)


posted by 대갈장군
2009. 9. 10. 00:29 프로그래밍
제목이 자극적이다. ㅋㅋㅋ

저놈이 바로 요근래에 날 괴롭힌 놈이다. 2009년 7월 31일자로 내 컴퓨터에 업데이트 된 놈인데 이놈은 언뜻봐서는 그 버전이 과거에 설치된 8.0.50727.762 보다 떨어지는 놈 같지만 이 어셈블리 번호는 꼭 크다고 우위를 선점하는 건 아닌가 보다.

아무튼, 이 업데이트 설치 후 VS 2005에서 컴파일 하는 C++ 프로그램은 이 어셈블리가 없으면 실행되지 않는다. 뭐 이 시스템에서는 실행할 수 없네 어쩌네 하면서 배째라고 한다.

Manifest 파일을 열어 확인해 본 결과 4053 이놈이 첫번째 줄에 떠억 자리하고 있는 것을 확인했고 이 녀석이 꼭 필요하다는 것을 알아챘다. 문제는 이 녀석이 자동으로 업뎃이 안되는 것 같다는 문제였다.

VS 2005가 설치된 컴에서는 자동으로 필수 업뎃으로 포함되는 것 같았으나 설치가 안된 컴에서는 일반적인 윈도우 업뎃으로는 설치가 잘 되지 않아 모든 Redistribution Package를 설치해야 했다.

암튼, 구글에서 Microsoft Visual C++ 2005 Service Pack 1 Redistributable Package ATL Security Update 를 검색하면 바로 다운로드 페이지가 뜬다. 

아마도 이런 문제를 겪은 사람은 별로 없겠지만... -_- 재수 없다면... 

암튼, .NET Framework가 어셈블리를 통해 일관성과 통일성을 추구하고자 했지만 간과한 것이 바로 이런 점이 아닌가 싶다. 필수 업데이트와 그렇지 않은 업데이트 간에 차이에서 오는 이런 사소한 실수가 어마어마한 시간의 낭비를 초래한다.

그리고, 업데이트 안하면 안되라고 들이대는 형식의 마이크로 소프트의 행태 또한 옳지 못하다. 뭐, 안되면 너희가 바보라서 그렇단다라는 식 아냐? 젠장... 


posted by 대갈장군
2009. 7. 30. 00:53 프로그래밍
C에서 가장 많이 발생하는 오류가 아마도 메모리 관련 오류가 아닌가 싶은데 이는 여러가지 원인이 존재한다. 여러개의 클래스가 겹쳐지고 상속되고 난리를 치다보면 이중해제를 하는 실수는 누구나 할 수 있다. 

이 문서는 http://www.yolinux.com/TUTORIALS/C++MemoryCorruptionAndMemoryLeaks.html을 참조하여 작성되었다.

1. C/C++에서 메모리 오류의 종류

일단 메모리 공간에 따라 크게 Heap Memory 에러와 Stack (local variables) Memory 에러가 있다. Heap 메모리 영역에서 발생가능한 에러는,

  1. 이미 해제된 메모리 다시 해제 할때
  2. 할당된적도 없는 메모리 해제 할라고 할때
  3. 이미 해제된 메모리 영역에 뭔가 데이터를 쓰려고 할때
  4. 할당된 적이 없는 메모리에 뭔가 데이터를 쓰려고 할때
  5. 메모리 할당 에러
  6. 동적으로 할당된 메모리 배열에서 초과된 index의 위치를 읽거나 쓰려고 할때 

1,2 번과 3,4번을 묶어서 볼 수 있는데 해제시에 발생하는 문제 vs 데이터 입력시 발생하는 문제로 볼 수 있다.

스택 메모리 영역에서 발생가능한 에러들로는

  1. 정적 배열에서 초과된 index의 위치를 읽거나 쓰려고 할때
  2.  함수 포인터 오류인데 잘못된 함수 포인터의 전달로 인한 잘못된 함수 호출


2. 메모리 누수!

메모리 누수는 할당한 동적 메모리를 제대로 해제하지 않고 프로그램을 종료하면 발생하는 것으로써 이것이 지속되면 컴퓨터의 RAM (빠른 메모리 공간)을 모두 소모하여 버리고 Page 파일 (하드 디스크에 생성하는 가상 메모리)를 남발하게 되여 컴퓨터의 성능을 저하시키다 결국 넉다운 된다. 

우선 이 웹사이트에서는 strdup() 함수를 예를 들어 설명하는데 좋은 예인거 같지는 않다. 아무튼 말하고자 하는 점은 malloc() 함수 (C library)로 할당된 메모리는 반드시 free()로 해제하라는 점이다.

요약하자면, 
   1. new로 할당하면 delete로 해제, malloc으로 할당하면 free로 해제.
   2. 할당 실패하면 해제 하지 말것. (할당되지도 않은 놈 해제하면 당연히 에러)
   3. 상속될 가능성이 있는 클래스의 파괴자는 반드시 가상 함수로 선언하라
   4. 포인터 사이에 대입연산 (주소복사)는 항상 메모리 누수 및 이중 해제의 가능성을 가진다.
   5. 클래스의 대입 연산자 사용시 얕은 복사가 잃어난다면 (주소만 복사) 역시나 누수와 이중해제의 위험 존재.

3. 메모리 부패 (Memory Corruption)

참 단어 선택이 오묘한데 부패라고 하니 꼭 이상한 듯 들리지만 오염보다는 나은것 같아서 그렇게 표현했다. 한국어로 뭐라해야 할지 모르겠다.

Memory Corruption은 사용자가 부주의하여 명확한 할당 없이 주소에 접근하여 데이터를 변경하려 하거나 잘못된 주소 위치로 접근하려 하는 경우를 말한다. 즉, 컴퓨터 입장에서 보면 메모리가 '부패'한 셈이다 :)

우선 흔히 발생하는 Buffer Overflow의 경우는 할당된 메모리 양보다 더 많은 데이터를 집어 넣을때 발생하는 것이고 또 다른 흔한 Memory Corruption은 할당한 배열을 초과하는 위치에 접근하는 경우다. (인덱스 초과)

그리고 또 흔한 경우로 포인터 변수로 선언한 변수에 new로 메모리를 할당하지도 않았는데 포인터 주소가 가지는 멤버 변수나 함수로 접근하는 경우다. 당연히 에러다.

free() 함수로 날려버린 변수에 접근하는 것 역시 '부패한 메모리'로의 접근이다. 

생각보다 중요한 것이 나오는데 new []로 배열을 할당한 경우 반드시 delete []로 삭제해야 한다. 이거 의외로 실수하는 경우가 많다.

함수를 호출하여 함수 내에서 선언된 지역 변수의 주소를 넘겨와 사용할 경우 그 지역 변수는 함수 리턴 된 후에 언제든 사라질 수 있는 위험을 안고 있다. 그래서 절대로 이렇게 사용하면 안된다는 점.. 명심하자.











posted by 대갈장군
2009. 7. 28. 02:48 프로그래밍/C++
나는 늘 같은 경험을 한다. 모르는 어떤 것을 알기위해 이것 저것 읽어 보다보면 끊어진 이해의 연결 고리들이 어느순간 한번에 이어지면서 한순간에 전체적인 흐름을 파악한다.

그 흐름이 파악되면 세부적인 내용은 너무나도 쉽게 쉽게 이해가 된다. 아무리 어려운 문법이라도 '음, 이건 분명 이렇게 될 수 밖에 없지...'라는 마치 알고 있었다는 듯한 느낌마저 받는다.

STL도 처음 나에게는 '이거 뭐야?' 라는 놈이었지만 지금은 '음, 이놈 복잡한 놈...' 이라는 정도의 느낌만 줄뿐 아예 모르는 놈은 아니다.

STL을 알기위해서는 템플릿도 알아야 하고 포인터에 대한 이해 및 함수 포인터 그리고 배열 및 객체 지향에 대한 이해도 필요하다.

하지만 이것은 실제적인 사용을 위해 필요한 것이고 이보다 앞서 필요한 '이해'를 위해서는 아무것도 필요없다. 무엇인가 알려고 할때는 항상 전체적인 흐름을 파악하고 왜 이것을 알아야 하는가에 대해서 먼저 답을 해야 한다.

그것을 알지 못하고 무작정 세부적인 문법만 파고들면 금새 길을 잃어버린 아이처럼 이곳 저곳을 방황하다가 결국 지쳐 울고 만다.

그렇다면 왜 사람들이 STL, STL하는지 알아보자. 과연 무엇이 그리도 좋다는 말인가?

STL은 한마디로 라이브러리다. 라이브러리... 도서관... 즉, 필요한 모든 정보가 있는 곳이다. 사용자는 이 STL을 이용해 수많은 똑똑한 개발자들이 만들어 놓은 아주 편리한 함수들을 손쉽게 꺼내어 사용할 수 있다.

프로그램을 작성하기 위해 필요한 두가지 필수 요소는 바로 알고리즘자료구조이다. 프로그램은 항상 저장된 데이터를 불러와 어딘가에 저장해 놓고 (자료구조) 그 값들을 필요에 따라 정렬, 삭제하여 (알고리즘) 원하는 것을 하는 것이다.

바로 이 두 가지 필수 요소인 자료구조와 알고리즘을 모조리 묶어서 정리한 라이브러리가 바로 STL이다. 

하지만 여기서 그치지 않는다. STL은 이름에서 처럼 Standard (일반화) 특성을 가지고 있다. 즉, 어떠한 자료구조이던 간에 상관없이 동일한 형태의 알고리즘을 제공한다는 점이다. 

이로써 사용자가 각 자료구조에 대한 각각의 알고리즘 (정렬, 삭제, 추가, 대입등) 을 일일히 정의해 줄 필요가 없어진 것이다.

이 얼마나 고마운 일인가...

게다가 STL은 이름에 있듯이 Template를 이용해 사용자가 원하는 임의의 형태로 객체를 생성해 낸다. 즉, int를 원하면 int, float을 원하면 float, 클래스를 원하면 클래스... 말 그대로 지 맘대로 객체를 생성할 수 있다.

고마워서 눈물이 날 지경이다... 상상을 해보라. 프로그래머가 자신이 사용해야 할 자료구조 (스택, 리스트, 큐) 같은 것을 프로그램 짤때마다 만들어야 한다면? 게다가 알고리즘까지 다 만들어야 한다면??

이런 복잡한 일을 다 해주는 고마운 친구가 STL인것이다.

그럼 아마도 이런 생각이 들것이다. 그럼 왜 진작부터 이거 사용안하냐고... 

좋은 질문이다... STL은 이해하기는 쉽지만 사용하기 위해서는 C++과 C에 대한 전반적인 이해가 필수이며 몇몇 단점들이 존재하기 때문이다.

우선 실행파일이 거대해 진다. 원래 STL은 속도만을 중요시 하기때문에 컴파일 타임에 링크하는 방법을 쓰지 않는다. 고로 정적 링크를 항상 하게 되므로 생성하는 STL의 객체 수와 사용하는 STL 함수만큼 정적 링크의 갯수가 늘어간다.

하지만 크기의 이점을 잃어버리는 대신 '편리함'을 얻었으니 불평하기만 할 수는 없지.

다른 문제점은 '가독성'이 열라 떨어진다는 점이다. STL을 이중 삼중으로 사용하게 되면 작성한 놈조차 '이게 뭔 말이여?' 라는 소리를 하게 되어 있다.

즉, 템플릿의 문법 자체가 복잡한데다가 일반화 특성을 추가해버렸으니 더더욱 복잡해 보인다. 그래서 제대로 사용하기 위해서는 많은 연습이 필요하다는 점이다.

많은 사람이 STL을 꺼려하는 이유는 복잡하기 때문인데다가 이를 대체할 좋고 쉽게 이해할 수 있는 MFC가 존재하기 때문이다. 

하지만 내가 얻은 소스가 STL이라면 어쩌겠는가? 즉, 결국은 알아야 한다는 말이지... 에휴... 만약 템플릿이 무엇인지 모른다면 반드시 그것부터 이해해야 한다는 말은 꼭 하고 싶다...
posted by 대갈장군