« Previous : 1 : 2 : 3 : 4 : Next »

비주얼 C++ 개발자에게 F12는 무척 특수한 의미를 갖는 단축키이다. 커서가 가리키고 있는 명칭(함수, 변수, 클래스 등~)이 선언되어 있는 위치로 바로 이동해 주는 기능이기 때문이다. Find in Files와 더불어 복잡한 소스 코드를 분석할 때 없어서는 안 되는 기능이다.

또한 Alt+F12는 Symbol 탐색기이다. 무수히 많은 파일들을 무식하게 문자 단위로 검색하는 게 아니라 최적화된 symbol 데이터베이스만을 뒤지기 때문에, 명칭만의 출처를 아주 빠르고 똑똑하게 찾을 수 있다.

사실 이 기능은 비주얼 C++ 6.0에도 있었고, 심지어 더 이전 버전도 갖추고 있었다. 그러나 그때는 이 기능이 활발하게 활용되지는 못했다.
이런 고급 기능을 사용하려면 프로그램의 전체 빌드를 Browse 정보를 남겨 놓는 방법으로 특수하게 다시 해야 했기 때문이다. 그리고 매번 빌드할 때마다 그 Browse 정보도 업데이트해야 했다. 그러므로 빌드 시간도 증가.

원래 C/C++이라는 언어 자체가 빌드 속도가 느린 데다, obj, pch, ncb 등 온갖 잡다한 output을 많이 남기는 걸로 악명 높은 언어이다. 언어의 범용성 보장이라든가 강력한 네이티브 코드 생성을 위해서 어쩔 수 없는 면모도 물론 있긴 하나, 현대의 언어들과 비교했을 때 생산성이 무척 떨어지는 건 사실. 그런데 그것도 모자라서 빌드 오버헤드까지 감수하면서 별도의 Browse 정보를 생성해야 한다니. Browse 기능을 쓰는 사람이 많을 수가 없었다.

내 말이 믿기지 않으면, 비주얼 C++ 6 갖고 계신 분은 프로젝트 하나 만들어서 아무 명칭에다 대고 F12를 눌러 보라. Browse 정보를 생성할 건지 묻는 질문부터 먼저 뜨는 걸 볼 수 있을 것이다.

그러다가 비주얼 C++ .NET이 출시되면서 장족의 발전이 이뤄졌다. 별도의 Browse 정보를 만들 필요가 없이, 빌드 한 번만 하고 나면 명칭 조회와 탐색이 아무 프로젝트에서나 가능해진 것이다. 굉장히 편리해졌다.

사실 이건 어찌 보면 자연스러운 귀결인 게, 비주얼 C++ 6.0부터는 어차피 인텔리센스 기능이 초보적인 수준이나마 추가됐기 때문이다. 함수의 원형이 마우스의 풍선 도움말로 뜨고 명칭을 자동 완성해 주는 기능은 Browse 기능과 성격이 상당수 비슷하지 않은가?

기술적으로 어떻게 변했는지 정확하게는 모르지만, 본인 생각에는, 둘이 서로 따로 DB를 구축하면서 따로 놀던 게 닷넷부터는 동일한 인텔리센스 데이터를 공유하면서 명칭 조회 기능과 인텔리센스가 모두 동작하도록 바뀌었지 싶다. 그래서 그런지, 편리해진 대신에 닷넷 초창기 버전은 과거의 6.0에는 있던 기능이 잠시 사라진 것도 있었다.

바로 함수에 대해서 Caller/Called by 그래프를 그려 주는 기능이다. 이 함수가 또 어떤 함수를 호출하는지 쭉쭉~ 아니면 이 함수를 사용하는 함수는 무엇이 있는지 쭉쭉~

그런데 인텔리센스 정도 구현하는 데는 명칭 자체에 대한 DB만 구축하면 되지, 명칭과 명칭 사이의 각종 인과관계를 따질 필요는 없지 않은가. 그래서 비주얼 C++ 2003(닷넷)에는 잘 살펴보면 저 기능을 어디에도 찾을 수 없다. 본인의 가설을 뒷받침하는 증거 중 하나이다.

잠시 없어졌던 그 기능은 비주얼 C++ 2005부터 완전히 부활했다. 인텔리센스 자체가 버전업을 거듭하면서 굉장히 강력해졌기 때문이다. 2003부터는 #define 심볼과 템플릿도 지원되기 시작했고, 2005/2008부터는 함수 포인터도 지원되기 시작했다. 예전에는 프로젝트를 별도로 빌드해서 파일로 조회를 해야 했던 정보가, 지금은 컴퓨터가 좋아진 덕분에 실시간 업데이트와 조회가 가능한 존재로 바뀌었다.

비주얼 C++ 2010은 듣자하니 인텔리센스 엔진이 또 완전히 바뀌었고, C#이나 베이직 같은 ‘쉬운 언어’에서나 지원되던... 빨간 선 기능(워드 프로세서의 맞춤법 검사기처럼.. 문법에 틀린 부분)이 흠좀무스럽게도 C++에도 도입되었다고 하더라.

인간의 프로그램 개발 환경의 생산성 개선을 위한 노력은 오늘날에도 계속되고 있다. ㄲㄲ

Posted by 사무엘

2011/06/07 19:10 2011/06/07 19:10
Response
No Trackback , 9 Comments
RSS :
http://moogi.new21.org/tc/rss/response/522

대학원에 간 뒤부터 컴퓨터나 프로그래밍 쪽 글은 눈에 띄게 줄고, 확실히 언어 쪽 글이 늘었다. 물론 철도 글은 예나 지금이나 비슷한 빈도로.. ㅋㅋㅋ
그래도 언젠가 한 번쯤 이런 글을 올리고 싶었다.

비주얼 C++ 4.2는 본인이 고등학교에 진학하고서 도스용 프로그램으로 정올 공모를 한 번 마친 후, 그때부터 공부하기 시작한 툴이다. 이때 윈도우 API, MFC, 심지어 C++ 객체 지향 개념까지 전부 뭉뚱그려서 동시에 공부를 시작한 셈이었다.
그로부터 10년이 지난 지금까지도 비주얼 C++은 나의 소중한 친구이고 내 마음의 고향이다. ^^;; <날개셋> 한글 입력기 1.0이 VC++ 4.2로 개발되었다.

참고로 4.2 버전은 4.0 버전이 몇 차례 마이너 업그레이드를 거친 것이었다. 4.2가 따로 4.0처럼 별도의 패키지로 출시되지는 않았으며, MSDN 구독자에게만 비공식적인 경로로 배포되었다고 한다. 이 점에서 4.2는 윈도우 95로 치면 마치 OSR2 업그레이드 에디션과 비슷한 위상이다.
지금은 윈도우든 개발툴이든 오피스든 MS에서 나오는 제품들은 다 서비스 팩이라는 개념으로 업데이트 방식이 통일되었지만 말이다.

그러나 4.2라는 버전은 굉장히 의미가 크다. 윈도우 운영체제가 시스템 차원에서 MFC 라이브러리의 하위 호환성을 보장해 주고 있는 최후 버전이 4.2이기 때문이다. 그 이름도 유명한 MFC42.DLL이다. MFC40.DLL이 아니다.

사용자 삽입 이미지

(<날개셋> 한글 입력기 1.0이 바로 윈도우 95 + 800*600 화면 + 비주얼 C++ 4.2 환경에서 개발됐다.)

그 전부터도, PC 환경에서 이제 윈도우가 대세로 넘어갔으니 윈도우 프로그래밍을 공부하려고 마음을 안 먹은 건 아니었다. 그러나 그때는 비주얼 베이직이나 델파이, C++ 빌더처럼 RAD 툴 수준에 머물러 있었다. 그러던 차에 접한 비주얼 C++은 굉장히 충격적이었다.
이 툴로는 다른 툴과는 달리, 운영체제와 직통으로 대화하고 다른 이상한 런타임이 필요하지 않은 가볍고 빠른 프로그램을 만들 수 있었기 때문이다.

비주얼 C++ 4.2 자체도 요즘 최신 버전에 비하면 정말 미치도록 작고 가볍다. ^^;;; 도움말은 RTF 기반이었고, C/C++ + 윈도우 API + MFC 레퍼런스를 전부 합해서 용량이 150MB 남짓밖에 안 했다. 그 당시 왼쪽의 class view는 실시간 업데이트가 되지 않았으며, 소스 코드를 저장해야 업데이트 됐다. ^^;;;
또한 프로그램 파일들이 압축되지 않은 형태로 CD에 그대로 들어있었기 때문에, 프로그램을 설치하지 않고도 CD에서 곧바로 MSDEV.EXE를 실행해서 프로그램을 실행할 수도 있었다. 물론 전기능을 제대로 활용할 수는 없었지만.

한동안 MS 오피스와 비주얼 C++은 요즘 서울 버스 색깔처럼 빨-노-초-파가 어우러진 4색 고리 모양 아이콘을 사용해 왔다. 4.2도 그랬다. 그런데 2010 버전은 둘 다 단색 아이콘으로 돌아갔으니 이 또한 흥미로운 점. 오피스는 노랑-주황색 사각형 창 4개 모양이 됐고, 비주얼 스튜디오(C++ 포함)는 보라색 ∞ 모양이 돼 있다.

세월이 흘러, 현재 <날개셋> 한글 입력기는 9개 모듈을 모두 비주얼 C++ 2008로 개발되는 중이다. 그러나 타자연습과 파워업은 적극적인 개발보다는 유지 보수만 하는 만큼 여전히 2003을 사용 중이다.

Posted by 사무엘

2010/10/29 16:10 2010/10/29 16:10
,
Response
No Trackback , 9 Comments
RSS :
http://moogi.new21.org/tc/rss/response/400

비주얼 C++ 2010 외

※ auto keyword

지금까지 signed와 더불어서 C/C++의 주요 '유명무실' 사문 예약어이던 auto가 비주얼 C++ 2010에서는 완전히 새롭게 거듭날 예정이다.
auto는 그 변수에 초기화해주는 값이 나타내는 타입을 그대로 부여해 준다. 즉,

int a=5; (...) auto b=a; 라면 b는 int형이 되고
vector<int> arr; auto itor=arr.begin(); 이라면 itor의 타입은 vector<int>::iterator 가 된다.

그래서 말 그대로 auto는, 뒤에 나오는 대입값을 보고 자료형을 '자동'으로 알아서 판단하라는 의미가 된다.
이런 게 언제 C++ 표준으로 상정됐는지는 모르겠는데, 기능과 문법을 만들어 놓은 방식이 정말 기발하고 참신하기 그지없다.
이 키워드 하나가 수많은 번거로운 자료형 하드코딩 타이핑 내지 typedef들을 예방해 주리라 기대된다.

당연한 말이지만 auto 자체는 sizeof 같은 연산자의 피연산자가 될 수 없다. 또한 auto가 무슨 비주얼 베이직의 variant 타입처럼 아무 자료형이나 수시로 집어넣을 수 있는 타입을 의미하지는 않는다.
auto 형으로 선언되는 개체나 변수는, 마치 참조자를 선언할 때처럼 반드시 선언과 동시에 값 대입 내지 초기화가 되어야 할 것이다.
C++은 함수의 인자 개수와 인자의 자료형으로만 오버로딩을 구현하지, 함수의 리턴값으로 오버로딩을 구현하지는 않기 때문에 이런 기능을 모호성 없이 구현할 수 있는 것이다.

이 외에 다른 이상한 C++ 문법도 도입되고 C++ 라이브러리 쪽에도 무슨 변화가 있는데 그건 잘 모르겠고,
프로젝트 파일 포맷이 또 바뀔 예정이라고 한다.

※ 비주얼 C++ 프로젝트 파일

여기서 잠깐 역사 수업. 비주얼 C++ 프로젝트 파일의 역대 계보는 다음과 같다.

1기 *.vcp는 16비트 1.x 초창기 시절에 쓰였다.
2기 *.mdp는 32비트 통합 IDE인 Developer Studio 초창기 시절인 4.x에서 쓰였다. 세월이 세월이니만큼, 1기와 2기는 지금은 거의 찾을 수 없는 전설의 파일 포맷이 돼 있다.
3기 *.dsw와 *.dsp는 드디어 여러 프로젝트를 한데 묶어 관리하는 워크스페이스라는 개념이 도입된, 5와 6 두 버전에서 쓰였다.
그 후 닷넷급이라 할 수 있는 비주얼 C++ 200x에 가서는 4기인 *.sln, *.vcproj 방식이 등장했다. 비주얼 베이직/C++/C# 모든 언어들의 프로젝트 사이에 일관성이 생겼으며 워크스페이스라는 명칭이 솔루션으로 바뀌었다. 그리고 프로젝트 파일은 내부 구조가 XML 형태로 바뀌었다.

이제 프로젝트 파일의 내부 구조가 또 바뀔 일은 없을 거라고 생각했는데 2010에서는 vcxproj라고 또 바뀔 거라고 하니 이게 웬일?
설마 MS 오피스 2007처럼 또 zip 압축을 하는 건 아닌가 모르겠다.
하지만 개발툴의 프로젝트 파일은 소스 버전 관리의 편의성 같은 이유도 있고 해서 다들 plain text 방식으로 저장하지, 바이너리 방식을 쓰지는 않을 텐데 말이다.

더구나 개발툴의 버전이 바뀔 때마다 각종 컴파일러 옵션들은 시시때때로 추가되거나 삭제, deprecate되기도 하기 때문에, 이런 프로젝트 파일들은 유연성, 하위 호환성, 확장성을 최대한 유지하는 게 짱이다. 즉 plain text가 정답이라는 뜻이다.

경험상 비주얼 C++ 2005하고 2008은 프로젝트 파일 포맷이 거의 차이가 없다.
sln과 vcproj 파일 앞줄에 있는 버전 번호만 1 줄여 주면, 2008로 만든 프로젝트도 2005에서 아무 문제 없이 바로 읽어들일 수 있다.

※ 비주얼 C++ 6.0이 나온 지 좀 있으면 벌써 12주년

얘기가 여기까지 왔는데 또, 애증이 교차하는 비주얼 C++ 6.0 얘기를 하지 않을 수 없다.
무려 11년 전엔 1998년에 출시되었고 아직까지도 애용되고 있는 소프트웨어로는 스타크와 더불어 양대 산맥이 아닌가 생각된다.
너무 구닥다리가 되어 외형이 후져 보이고(비록 당대로서는 MS 오피스 97 스타일의 새끈-_-한 UI였지만),
64비트 지원 안 되고 최신 하드웨어 기술 및 C++ 표준이 반영 안 돼 있는 것 자체만 빼면 정말 잘 만든 물건이긴 하다.

가끔은 6.0 특유의 그 클래스 마법사가 그리워질 때도 있다.
MFC는 이제 <날개셋> 타자연습 소스 열어볼 때 말고는 별로 접할 일도 없어졌구나.

그 비주얼 C++이 곧 있으면 연도도 2010이고 버전 번호로도 10.0이 나올 예정이다. 감회가 새롭다.
참고로 비주얼 C++ 2005는 2005년 하반기에 나왔지만 2005라는 타이틀이 붙은 반면,
2008은 비슷한 2007년 하반기에 출시됐지만 1이 더해진 2008이라는 타이틀이 붙었다.

※ 여자 프로그래머

7월 1일.. 경의선 전철 개통, 용인-서울 고속도로 개통, 거기에다 비정규직법 상정 2주년-_- 등 여러 굵직한 일이 많았는데, 나도 이제 병특 끝난 지 1주년이 됐다.
그리고 직장 생활 경력이 3년을 넘어갔다. 최소한 말단 신입사원 딱지는 떼는 짬밥이 됐고, 주임/대리급을 바라보는 신분이다. 하지만 옛날 회사나 지금 회사나 여전히 제일 나이가 어리고 내 밑으로 신입을 대한 적이 없으니, 예나 지금이나 늘 막내이다.

그리고 내가 지금까지 다닌 회사에서 여자 개발자를 본 적은 전혀 없다.
IT 회사라고 해도 여직원 하면 오로지 디자인, 기획 아니면 회계/경리이다. 개발자가 여자인 경우는.. 글쎄다.
하지만 외근 나간 연구소에서는 그래도 비주얼 C++ 띄워 놓고 코드와 씨름하고 있는 여자분들을 주변에서 여럿 볼 수 있어서 인상적이었다.

차라리 학교에 있을 때는 그런 모습을 심심찮게 볼 수 있었다. 내가 나온 학교는 공대 중에서 성비가 상당히 균형 잡힌-_-;; 편에 드는 곳이었으며, 전산과 역시 예외가 아니었기 때문이다.
하지만 나는 학교 시절엔 과 친구들하고 거의 어울리지 않고 동아리 같은 것도 안 하고 지냈기 때문에 그런 학우들로부터는 이렇다할 '임팩트'를 받지 못했다.

여직원하고 "아.. 그 땐 이런 함수를 쓰면 돼요"
"이 클래스는 여기서 상속 받았고 이 가상 함수는 이런 용도로 오버라이드하면 됩니다. 대략 이렇게 구현을 하면 어떨까요?"
"아 그렇게 생각해 보니 이렇게 짜면 버퍼 오버런이 우려되고, 멀티스레드 환경에서는 잠재적으로 또 문제가 있겠군요"
이런 이야기를 나눈다면.. 졸라 감회가 새로울 것 같다. 태어나서 이성하고 그런 얘기는 한 번도 한 적이 없으니까. =_=

하긴, 부부 교사도 있고,
커플이 나란히 코레일에 입사하여 기관차 운전 연수를 받던 부부 기관사도 봤는데, (촬영 당시 곧 결혼 예정이라고 쓴 걸 봤음)
부부 개발자라고 없을 이유는 없으리라 생각한다. -_-

Posted by 사무엘

2010/01/11 10:10 2010/01/11 10:10
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/86

class CAppFrame: public CWnd {
public:
        void PostNcDestroy() { delete this; }
};

class CMyApp: public CWinApp {
public:
        BOOL InitInstance();
};

CMyApp g_App;

BOOL CMyApp::InitInstance()
{
        m_pMainWnd=new CAppFrame;
        m_pMainWnd->CreateEx(0, AfxRegisterWndClass(0), _T("Hello World"), WS_OVERLAPPEDWINDOW,
                100, 100, 500, 500, NULL, NULL);
        m_pMainWnd->ShowWindow(SW_SHOW);
        m_pMainWnd->UpdateWindow();
        return TRUE;
}

위의 코드는 MFC를 써서 만들 수 있는 가장 간단한 GUI 프로그램이다. 빈 창만 달랑 뜨는 게 허전하면, message map 넣고 OnPaint에다가 Hello, world! 출력하는 코드만 추가해 주면 된다.
MFC로 창을 띄우기 위해서는 본질적인 것 딱 두 가지만 기억하면 된다.

첫째, CWnd에서 상속 받은 클래스를 만들기

둘째, CWinApp에서 상속 하나 받아서 전역 개체를 하나 반드시 만들고, InitInstance를 오버라이드하여 내 윈도우 클래스를 생성하는 코드를 짜 주기

물론 요즘은 닷넷 프레임워크 같은 더 객체 지향적이고 깔끔한 API도 나와는 있지만 저 정도만 해도 그냥 C언어 + Win32 API만 썼을 때와는 비교할 수도 없이 간단하게 내가 원하는 일을 곧장 시작할 수 있다. 윈도우 클래스 등록, 윈도우 프로시저 등 온갖 지저분한 내부 처리를 상당 부분 MFC가 알아서 해 주기 때문이다.

MFC의 핵심부이며 가장 자주 다루게 되는 부분은 역시 윈도우를 나타내는 CWnd 관련 개체이다. 응용 프로그램의 메인 윈도우부터 시작해서 대화상자와 대화상자 안의 자그마한 컨트롤까지 매우 다양한 용도로 쓰이는 HWND를 한 뿌리 클래스와 상속 클래스만으로 원활히 제어하기 위해 MFC는 굉장히 심도 있게 설계되었으며 내부적으로 자질구레한 일들을 매우 많이 해 주고 있다. 단순히 ShowWindow(hWnd, SW_SHOW)를 wnd.ShowWindow(SW_SHOW)로 바꿔 주는 것을 훨씬 넘어서는 수준이다.

더구나 메시지 맵을 통해 컨트롤 서브클래싱(기존 윈도우 컨트롤의 동작을 부분적으로 조작하는 것)까지 매끄럽게 연결시킨 것까지 보면, 솔직히 굉장히 잘 만든 프레임워크임을 인정하지 않을 수 없다.

이런 프레임워크를 만들 때 근본적으로 문제가 되는 것은 CWnd라는 C++ 오브젝트와 운영체제의 HWND 사이의 씽크를 맞춰 주는 작업이다. 둘은 원래 개념적으로 생성 주기나 scope이 서로 완전히 다른 존재이다. 하지만 MFC는 한 HWND를 가리키는 CWnd 오브젝트가 중첩되지 않도록 배려하고 있으며, 나의 C++ 코드에 의해 생성되지 않은 외부 HWND에 대해서도 임시 맵까지 만들어 가면서 CWnd를 동기화해 주고 있다. 멀티스레드 환경까지 감안하면 이는 더욱 복잡한 작업이 된다.

new 연산자로 CWnd가 생성될 때 CreateWindow를 같이 해 주고, HWND가 완전히 소멸되어 WM_NCDESTROY가 왔을 때 CWnd까지 delete로 지워 주는 것은 대부분의 경우엔 바람직한 디자인 패턴이나, 이것이 언제나 유용한 것은 아니다. 가령 modal 대화상자는 자체적으로 message loop까지 갖추고 있기 때문에 heap이 아닌 스택에다가 간단히 지역변수로 선언하는 경우가 더 유용하기 때문이다. 더구나 대화상자는 사용자가 대화상자를 닫았더라도, 이 C++ 클래스 갖고 있는 데이터 변수들을 후에 활용하는 경우가 많기 때문에 HWND 개체가 사라진 뒤라도 C++ 개체는 남아 있어 줘야 한다.

이래저래 CWnd와 HWND 사이의 관계와 생성/소멸 주기는 여러 모로 이해하기 까다롭다. CWnd 클래스 중에서 new로 생성되고 HWND의 소멸과 동시에 소멸되어야 하는 오브젝트라면, PostNcDestroy 함수를 오버라이드하여 delete this를 넣어 주어야 메모리 누수가 발생하지 않는다. 응용 프로그램의 주 프레임 윈도우라든가 modeless 대화상자가 이런 예에 속한다.

저 소스 코드에서는 CWnd를 날것으로 사용했지만, CWnd에서 파생되어 아예 전문적으로 응용 프로그램의 주 프레임 윈도우를 담당하고 있는 MFC 클래스인 CFrameWnd는 PostNcDestroy가 이미 저렇게 구현되어 있다. 그뿐만 아니라 이 클래스는 LoadFrame 함수에서 이미 윈도우 클래스의 등록까지 다 알아서 해 주기 때문에 저 소스 코드에서처럼 AfxRegisterWndClass를 번거롭게 호출할 필요도 없다. 사용자가 준 ID와 일치하는 응용 프로그램 타이틀, 아이콘, 심지어 단축키 액셀러레이터 테이블 따위를 모두 엮어서 윈도우의 기반을 자동으로 구성해 주기 때문이다.

MFC를 써서 아주 간단한 프로그램을 짜고 싶은데 비주얼 C++의 MFC 마법사가 기본으로 생성해 주는 코드는 군더더기가 너무 많다. 그래서 이럴 때 본인은 MFC 없이 일반 Win32 응용 프로그램으로 프로젝트를 시작한 후, 저 코드 템플릿을 갖다 붙이고 프로젝트 세팅을 “MFC 사용”으로 수동으로 바꾸는 방법을 쓴다.

필요한 건 MFC가 잘 캡슐화해 준 message loop, 몇몇 GDI 오브젝트 같은 것밖에 없는데 이것만 쓰기에는 MFC는 덩치가 너무 커지고 static link를 하기에도 오버헤드가 너무 큰 것도 불만이다. 차라리 known DLL만 쓰기 때문에 매우 가벼운 바이너리를 만들 수 있는 비주얼 C++ 6.0이 그리울 때도 있다. 어차피 이후 버전에서 추가된 기능은 거의 안 쓰기 때문에.

<날개셋> 타자연습은 소스를 보면 알겠지만 딱 MFC를 써서 개발되었다. 하지만 한글 입력기는 3.0부터 MFC를 쓰지 않으며, 믿거나 말거나 MFC를 어설프게 흉내 내어 본인이 내부적으로 자체 개발한 프레임워크 라이브러리를 static link하여 개발해 오고 있다. 하지만 자체 라이브러리는 오버헤드 줄이고 최대한 가볍게 만드느라, Win32 API라든가 각종 핸들을 캡슐화한 수준이 MFC 수준으로 범용적이고 체계적이고 편하지는 못하기 때문에, 여전히 MFC가 그리울 때가 있다. ^^;;

Posted by 사무엘

2010/01/11 00:27 2010/01/11 00:27
,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/50

비주얼 C++의 역사

그동안 비주얼 C++에 대한 글을 적지 않게 썼었는데 이렇게 전버전의 특징과 역사를 정리해 본 적은 없는 것 같다.
역시 2003과 2005에 대한 설명이 가장 길다.

※ 1.0

MS C 7.0의 차기 버전으로서, 비주얼 베이직처럼 비주얼이라는 브랜드를 걸고 첫 제품이 출시되었다. 비주얼 C++의 역사는 초기에 Application framework라 불리던 MFC 라이브러리와도 역사를 함께 한다.

※ 1.52

윈도우 3.1 타겟을 지원하는 마지막 버전인지라 굉장히 중요한 위치를 차지하고 있다. AppStudio라는 통합 환경이 있기는 하나 도움말 열람, 리소스 편집 등은 여전히 다른 프로그램에서 따로 해야 했다.
프론트 엔드 GUI는 모두 16비트 프로그램인 반면, 커맨드 라인에서 동작하는 컴파일러, 링커 같은 주요 툴들은 도스 익스텐더 stub을 내장하고 있는 32비트 PE 포맷인 점이 무척 인상적이다.

이 시절에 컴파일러는 도스/윈도우 모두 그것도 메모리 모델별로 다 지원해야 했기 때문에 타겟 지정하는 옵션이 무척 까다로웠던 것 같다. 그리고 kernel32, gdi32, user32처럼 API가 분야별로 나뉘어 있는 게 아니라 윈도우 API import 라이브러리가 한 파일에 다 들어있었다.

군대 갔다 온 분, 특히 육군 쪽으로 갔다 온 분은 ‘상호 존중과 배려’라는 표어에 매우 익숙할 것이다. 실제로 이걸로 검색해 보면 군대 관련 사이트, 블로그 포스트들이 제일 먼저 많이 뜬다. -_-;;
그런데 윈도우 3.1만큼 이 문구가 잘 들어맞는 환경도 별로 없을 것 같다. 프로세스들이 혼자 시스템 자원 CPU 시간을 절대 독점하지 말고 다른 프로세스에 대한 자발적인 ‘상호 존중과 배려’로 멀티태스킹을 서로 만들어 가야 하기 때문이다. ^^;;

※ 2.0

32비트 타겟으로 나온 첫 버전으로 알려져 있으나, 그 시기가 윈도우 95가 나오기도 전이고 NT는 점유율이 미미하던 때였다. 시대를 너무 앞서 가는 바람에 주목을 별로 못 받은 전설 같은 존재이다.
(그나저나 그렇다면 94년 이전에 윈도우 NT 3.1의 각종 바이너리들은 무엇으로 빌드했는지 궁금하다. MS 자체적으로만 쓰는 내부 컴파일러? ㄱ-)

32비트 환경에서는 메모리 모델 구분이 없는 대신, CRT에 링크 방식(static/DLL)과 멀티스레드 지원 여부라는 개념이 새롭게 생겼다.

※ 4.0

DirectX에 4라는 버전이 없는가 하면 비주얼 C++에는 3.x대 버전이 없다. 내부적으로 꾸준히 버전업이 돼 온 MFC의 버전 번호에 맞춰 곧바로 4.0으로 건너뛰게 된다. 참고로 윈도우 95의 워드패드가 웬 듣보잡 MFC 3.0 기반인 점이 흥미롭다. 98 이후부터는 전부 MFC42 기반으로 바뀌었음.

4.0에 와서야 비로소 오늘날의 비주얼 C++과 상당한 골격이 갖춰졌다. 즉 코딩, 리소스 편집, 클래스 마법사, 도움말 열람을 한 프로그램에서 할 수 있는 진정한 통합 환경 Developer Studio가 이 버전부터 생겼다. msdev.exe라는 프로그램 이름은 훗날 6.0까지 이어졌다.
이때는 아직 16비트에서 32비트로 한창 넘어가는 과도기였기 때문에 Win32s 타겟이 지원되기도 했다.

참고로 MS에서 개발한 프로그램 중에서 MFC를 쓴 놈은 고작 워드패드, 그림판, 그리고 비주얼 C++ 6 이하 버전의 IDE와 관련 몇몇 유틸리티(Spy++, Dependency Walker) 정도? -_-;;

※ 4.2

4.1을 거쳐 4.0이 마이너 업그레이드된 버전으로, 제법 인지도를 얻었다. ActiveX 컨트롤, STL 같은 기능이 추가되고 MFC DLL의 이름도 이때부터 MFC42로 이름이 바뀌어 큰 뼈대의 변경 없이 훗날의 6.0까지 이어졌다. MFC42는 윈도우 98 이래로 운영체제가 이제 known DLL로 인정하는 마지막 버전 숫자이기도 하니 더욱 의미가 있다.

4.2에서부터 Win32s의 지원이 중단되었다. 오죽했으면 설치할 때 “이 버전부터 Win32s를 더 지원하지 않으니, 그 환경 개발하고 싶으면 이거 설치하지 말고 옛날 버전 쓰셈!”이란 경고문까지 나온다.

※ 5.0

GUI 껍데기는 거의 다 6.0처럼 바뀐 반면, 내부 구조와 기능은 여전히 4.2와 비슷하다고 보면 되겠다. 도구모음줄과 메뉴가 MS 오피스 97 스타일로 바뀌고(하지만 내부 코드 베이스는 서로 완전히 다름) 대화상자도 리모델링되었으나, 도움말은 여전히 RTF 기반이고 인텔리센스도 아직 없었다. 이듬해에 나온 6.0에 밀려 완전히 존재감을 상실했다. 프로젝트 파일 포맷이 이때 처음으로 DSP, DSW로 바뀌었는데, 이 포맷은 결국 5와 6 두 버전에서만 쓰이고 이후 버전에서는 또 바뀌게 되었다.

이때부터 bool이 built-in type으로 지원되기 시작했다. 그리고 이때부터 빌드하는 EXE 파일에 PE 재배치 정보가 기본적으로 생략되게 되었다.

※ 6.0

나온 지 10년이 지난 지금도 어렵지 않게 찾을 수 있고, 윈도우 XP만큼이나 최장수 개발툴로 이용되고 있는 결정판이다. 이 버전 이후로 거의 4년 가까이 버전업이 없었고 다음 버전인 닷넷이 변화폭이 너무 크기도 했기 때문이다.

6에서는 인텔리센스, edit and continue, delay-loaded DLL 같은 획기적인 기능이 처음으로 추가되고 도움말이 별도의 MSDN 라이브러리로 독립함과 동시에 HTML 기반으로 모두 바뀌었다.
이 버전은 윈도우 9x에서 설치 가능한 마지막 버전임과 동시에 MSVCRT, MFC42 같은 known DLL만 사용하는 바이너리를 생성할 수 있는 마지막 버전이기도 하다. 주요 라이브러리를 DLL 링크하고도 DLL 배포 걱정을 할 필요가 전혀 없다는 장점이 있다.

4.2 때는 ClassView에 있는 각종 클래스, 변수 정보가 소스 파일을 매번 저장할 때에만 업데이트됐다. 이것이 내용이 바뀔 때마다 실시간으로 바뀌기 시작한 것도 5.0은 아니고 6.0부터인 걸로 기억한다.

※ 7.1 (2003)

비주얼 C++의 다음 버전은 처음엔, 버전 번호나 연도가 아닌 닷넷이라는 브랜드로 출시되었다. MFC를 써서 개발된 VC 특유의 전통적인 msdev.exe는 퇴출되고 devenv라는 MS 오피스 내지 비주얼 베이직 스타일의 IDE가 등장했는데, 이는 완전히 새로운 것이라기보다는 예전에 비주얼 스튜디오에 있던 Visual InterDev와 비슷한 형태였다. 단지 거기에다 외형만 MS 오피스 XP 스타일 UI를 그대로 물려받았다.

덕분에 비주얼 C++과는 영 인연이 없고 비주얼 베이직만의 전유물인 것 같던 Property grid가 도입되어 비주얼 C++ 특유의 등록정보 대화상자를 대체했다. 클래스 마법사도 이 형태로 대체됐다. 도움말은 5.0 시절처럼 IDE 내부에 띄울 수도 있고 6.0처럼 외부에 띄울 수도 있는 융통성 있는 형태로 바뀌었다.

이제 주류로 내세운 게 C#, 공용 언어 런타임 같은 닷넷 환경이긴 했지만 네이티브 C/C++ 쪽도 크게 향상되었다. 6이 표준대로 제대로 지원하지 않던 문법 내지 컴파일러의 버그 많이 수정되기도 하고 네이티브 wchar_t 형식이 지원되기 시작했으며, 6에서 첫 도입됐던 인텔리센스도 굉장히 강력해져 특히 #define 심볼에 대해서도 동작하기 시작했다. 링크 시점에서 코드를 생성하는 전역 최적화라든가 crash mini-dump 생성 기능도 이때 첫 도입된 기능이다. 닷넷 정도만 써 보면 이제 6.0은 충분히 열악함을 느끼기에 충분할 것이다.

공용 라이브러리는 이제 MSVCR71, MFC71로 바뀌었는데, 이 DLL은 최신 운영체제라고 해서 더는 기본 내장을 해 주지 않기 때문에 응용 프로그램이 알아서 자기 디렉터리나 윈도우 시스템 디렉터리에다 구비해야 한다. 이 점에 관한 한 6.0이라든가 side-by-side assembly를 사용하는 8.0 이후만도 더 못하고 무책임한 면이 없지는 않다. 또한 64비트 개발은 불가능하지는 않으나 불편하고 디버깅도 되지 않고 IDE 차원의 적극적인 보조는 못 받는 어정쩡한 위상을 차지하고 있다. 이 불완전한 면모들은 후속 버전인 8에서 보완되었다.

사실 7.1은 최초로 나왔던 ‘닷넷’(7.0)의 버그 수정판이다. 엄청난 기능이 도입되었던 만큼 첫 버전은 불안정하고 버그도 많았기 때문이다. 7.1 버전은 아래아한글, VMware, 스타크래프트 같은 다수의 상용 프로그램의 최신 버전 개발에 아직까지 쓰이고 있다.

※ 8.0 (2005)

이 버전부터 닷넷이라는 이름을 떼고 출시는 되었으나 8은 7.1하고 아무 단절도 없이 닷넷과 네이티브를 모두 지원하는 동일한 개발 도구의 연장선이다. 이 버전은 닷넷 초창기 버전인 7의 과도기적 불완전하고 2% 부족하던 면모를 속 시원히 보완한 게 무척 많았다. 요즘 어도비 사에서 나오는 프로그램들이 이 버전으로 개발되고 있다.

첫째, 별도의 플랫폼 SDK를 설치할 필요 없이 IDE 차원에서 64비트 빌드와 디버깅이 정식 지원된다.
둘째, 공용 DLL인 MSVCR80, MFC80의 배포 방식이 side-by-side assembly 방식으로 완전히 바뀌었다. 일각에서의 불만을 감수하고라도 이건 꽤 강한 정책이었다. 이와 덩달아, 리소스 편집기로 수동으로 해야 하던 메니페스트 생성/편집 기능도 상당 부분 자동화됐다.

셋째, for 문의 변수 scope처럼 그동안 표준을 어기고 있던 문법을 교정하고, CRT의 보안을 크게 강화했다. strcpy_s와 gets_s(대상 버퍼 크기), qsort_s(콜백 함수에 데이터 전달 가능), strtok_s(토큰 중복 호출 가능) 같은 함수가 새롭게 등장하고 strchr 같은 경우, C++에서는 const 포인터를 되돌리는 버전과 비const 포인터를 되돌리는 함수가 오버로딩으로 분리해 나갔다. 무척 신선한 변화라 느껴진다. STL 디버깅도 훨씬 더 편해졌다.
넷째, UI 상으로도 이제 MS 오피스 스타일에서 독립한 새로운 외형 비주얼을 갖기 시작했으며, 도구모음줄 아이콘도 256색으로 더 화려해졌다. 전통적으로 ClassView에 클래스와 멤버들이 한 트리에 쫙 나열되던 것이 멤버는 별도의 리스트에 뜨도록 바뀌기도 했다.
이 버전부터는 생성하는 프로젝트의 디폴트 기반 인코딩이 드디어 유니코드로 바뀌었다.

※ 9.0 (2008)

8이 질적으로 많이 바뀌었다면 9는 윈도우 비스타의 등장처럼 8 출시 이후에 생긴 변화를 IDE나 MFC 라이브러리 같은 데에 적극 반영하여 양적인 향상을 꾀했다. 또한 MS 오피스 스타일의 GUI를 손쉽게 만들 수 있는 feature pack을 드디어 도입하기도 했다.

이렇게 시대의 조류 때문에 생긴 변화를 제외하면 9는 네이티브 C/C++의 관점에서 봤을 때, 7에서 8로 넘어갈 때 같던 큰 변화는 느껴지지 않으며 따라서 8은 조만간 별다른 존재감 없이 9로 흡수될 걸로 예상된다. 완전히 새로운 기능으로는 보안 강화를 위해 링커에 추가된 시작 주소 랜덤화 기능 정도? 이 옵션은 MS 오피스 2007과 윈도우 비스타의 모든 바이너리에 기본 적용돼 있으며, 과거 Win32s의 잔재로나 기억되던 EXE 파일의 재배치 정보를 다시 끌어들인 장본인이기도 하다.

9는 8과는 달리 윈도우 2000도 설치되지 않으며, 윈도우 9x 계열은 아예 타겟 플랫폼에서도 완전히 제외되었다. 링커 옵션에서 바이너리의 최소 요구 운영체제 버전이 4에서 5로 껑충 뛰었고, 이보다 낮은 값은 지정 자체가 안 된다.
또한 single threaded CRT 라이브러리 옵션도 없어졌다. 이것만 빼면 그다지 아쉬울 것 없다.

Posted by 사무엘

2010/01/10 23:50 2010/01/10 23:50
,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/41

1. 프로젝트의 링커 옵션 수정

"링커-입력" 카테고리의 "추가 종속성"에다가 같이 링크할 라이브러리 이름을 입력하는 것으로, 가장 일반적인 방법이다. 이 설정은 해당 프로젝트에 대해 전역적으로 적용된다. (당연히)

라이브러리 파일을 찾는 디렉토리 순서는 "링커-일반" 카테고리의 "추가 라이브러리 디렉토리"에다가 설정해도 되고, 아예 "도구-옵션" 명령의 "프로젝트 및 솔루션-VC++ 디렉토리" 카테고리에다가 완전 전역적으로 설정해도 된다.

하지만 내가 관리하는 프로젝트를 어느 컴퓨터의 비주얼 스튜디오에서나 바로 빌드하고 싶다면(외장 하드 같은 데에 담아다가), 디렉토리 순서는 후자의 애플리케이션 단위가 아닌 전자의 프로젝트 단위로 지정해 두는 게 좋을 것이다.
사실, "도구-옵션" 명령의 디렉토리 설정에다가는 C/C++ 기본 라이브러리나 윈도우 플랫폼 SDK 같은 완전 기본적인 디렉토리만 설정해 두고, 내 프로젝트에 특화된 디렉토리는 지정하지 않는 걸 추천한다.

2. 프로젝트의 구성원으로 라이브러리 파일 자체를 추가

한 프로젝트를 이루고 있는 여러 소스 파일들 중, 컴파일러 같은 특정 빌드 도구를 거치지 않은 파일은 자동으로 링커에게 그대로 전달되게 된다.
그렇기 때문에 굳이 링커 옵션을 지정하지 않더라도 프로젝트에 포함되어 있는 lib 파일은 링크 과정에서 자동으로 인식되고 사용된다.

지정하려는 라이브러리가 다른 SDK가 아니라 역시 내가 만들고 수정하고 관리하는 것인 경우에는, 이렇게 해 두는 것도 괜찮다. 특히 링커 옵션이나 "도구-옵션" 설정에 지정되어 있지 않은 임의의 디렉토리에 있는 아무 라이브러리나 자유롭게 참고할 수 있다는 장점이 있다.
단, 이 방법은 debug/release 같은 configuration별로 한 라이브러리의 여러 변종 파일을 지정하기가 좀 까다롭겠다.

옛날에, 거의 비주얼 C++ 6 시절엔, DLL을 만들 때 쓰이는 모듈 정의 파일(def)도 그냥 소스 파일로 프로젝트에다 집어넣어 놓으면 링크할 때 알아서 인식이 됐던 것 같은데 닷넷 이상부터는 안 그런 것 같다. 반드시 "링커-입력" 카테고리의 "모듈 정의 파일"에다 이름을 넣어 줘야 하는 듯.

3. #pragma 지시문

전체 프로젝트 파일 중에서 극소수의 소스 코드만이 특정 희소 API를 사용하기 때문에 그 놈에 대해서만 추가 라이브러리 링크 지정이 필요한 경우엔, 그 소스 파일에다가만
#pragma comment( lib, "rare_lib.lib" )

이렇게 지정해 주면 아주 간단하고 편리하다. 프로젝트 파일 차원에서의 수정이 없으며 한 소스 파일을 여러 프로젝트에서 공유할 때 관리가 용이해진다. 물론 표준이 아니라 MS 컴파일러 확장이긴 하지만.
이 소스를 컴파일하여 생긴 obj 파일의 내부에는, "나중에 나를 읽어들이는 링커님은 내가 가진 심볼들을 링크할 때 요 lib 파일도 추가로 좀 참고해 주셈"이라는 힌트 정보가 포함되게 된다.

이 방법은 static library를 만들 때 유용하다.
A라는 클래스 라이브러리를 빌드하는데, 얘는 B라는 다른 라이브러리의 함수를 참고하는 C라는 메소드를 멤버로 가지고 있다고 치자.
그리고 나는 D라는 애플리케이션을 A 라이브러리를 기반으로 개발하고 있다고 치자.

이 경우, D는 C라는 메소드를 호출하지 않더라도 링크할 때 A뿐만 아니라, 사용하지도 않는 B 라이브러리를 역시 지정을 해 줘야 한다. 그렇지 않으면 링크 에러가 난다.

하지만 라이브러리의 소스 코드 자체에 내가 의존하는 다른 라이브러리에 대한 정보가 이미 포함되어 있으면, 사용자는 그 내부 의존성에 대해서 알 필요가 없어지는 것이다. C 메소드를 사용하든 안 하든 D 프로젝트는 B 라이브러리의 링크 지정을 안 해도 되게 된다.

Posted by 사무엘

2010/01/10 22:55 2010/01/10 22:55
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/23

※ once -- 컴파일러의 동작 방식을 바꿈

비주얼 C++ 거의 6.0 시절부터 지원되었던 것 같습니다.
헤더 파일의 첫 줄에다 삽입하여 이 헤더가 중복 인클루드되지 않도록 합니다.

헤더 파일 전체를 #ifdef, #endif로 싸는 것보다 간편해서 좋습니다.
물론, 이걸 쓰면 특정 헤더 파일이 인클루드됐는지의 "여부"는 알 수 없지만, 그런 거 상관없이 중복 인클루드만을 방지하려는 용도로 아주 적합하지요.

※ comment -- 오브젝트 파일에 뭔가 정보를 기록함

- lib: 프로젝트 전체의 링커 옵션을 일일이 바꾸지 않고도 이 오브젝트 파일을 링크할 때는 이 라이브러리를 추가로 찾아 보도록 지정합니다. 매우 유용합니다.
- linker: 이 소스 코드에만 적용할 링커 옵션을 아예 소스 코드에다 바로 써 넣을 수 있습니다.
비주얼 C++ 2005는 예전까지 번거롭게 리소스로 처리하던 side-by-side 메니페스트 작성을, 링커 옵션으로 지정하여 전용 도구로 손쉽게 할 수 있게 되었습니다. 내 exe가 윈도우 XP 비주얼 스타일을 지원하고 싶으면 그냥 /manifestdependency를 지정하는 링커 옵션 pragma를 한 줄 써 주면 끝이라는 것입니다.

※ pack -- 컴파일러의 코드 생성 방식을 바꿈

위의 pragma 지시들이 그냥 다른 기능이나 옵션 설정만으로도 실현할 수 있는 기능에 대한 '편의'만을 제공하는 거라면, 이건 뭔가 고유한 의미를 갖는 기능입니다. 대체할 수 있는 다른 기능이 없습니다. 바로 구조체 패킹 관련 설정을 제어하는 것이기 때문입니다.

이건 근래에는 32비트 코드를 64비트 코드로 포팅할 때 특히 신경써야 합니다. 평소에는 기계가 처리하기 적당하게 32비트 내지 64비트 크기로 패킹을 하지만, 파일을 한 구조체로 바로 읽어들이거나 네트워크 패킷처럼 크기에 아주 민감하게 구조체를 짜려면 반드시 8 또는 16비트 크기의 정밀한 패킹이 필요합니다.

구조체 패킹 크기 옵션은 컴파일러가 스택 구조로 처리하기 때문에, 나의 새로운 설정을 집어넣었다가(push) 다시 예전 설정으로 돌아가는(pop) 식의 세팅이 가능합니다.

Posted by 사무엘

2010/01/10 22:25 2010/01/10 22:25
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/10

« Previous : 1 : 2 : 3 : 4 : Next »

블로그 이미지

철도를 명절 때에나 떠오르는 4대 교통수단 중 하나로만 아는 것은, 예수님을 사대성인· 성인군자 중 하나로만 아는 것과 같다.

- 사무엘

Archives

Authors

  1. 사무엘

Calendar

«   2020/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      

Site Stats

Total hits:
1442347
Today:
159
Yesterday:
482