※ 2000

일반 사용자를 대상으로 NT 커널과 9x 계열의 통합을 야심차게 기획했던 운영체제이다.
하지만 윈도우 디렉터리의 이름은 여전히 Windows가 아닌 WinNT였고, 특이하게도 마우스 포인터의 이동 자취(trail)를 남기는 기능이 없었다. 9x 계열은 말할 것도 없고 구닥다리 윈도우 3.1조차 갖추고 있는 기능인데 NT에서만 원래 없었던가? 물론 XP부터는 이 기능이 있다.
탐색기에서 wav/mp3을 클릭 후 바로 재생이 가능하던 유일한 운영체제이다.

그리고 2000부터 GUI의 표준 색상이 약간 바뀌었다. 그저 RGB(192,192,192)이던 회색은 살짝 더 누르스름하게 바뀌고, 파랑은 좀더 어둡고 군청색에 가깝게 바뀌었다.
그런데 유독 윈도우 2000만.. 스타크래프트 같은 256색 전체 화면에 들어갔다가 나오면 그 파란색이 예전의 덜 어두운 색으로 돌아가는 신경 쓰이는 버그가 있었다. 이 역시 ME라든가 XP 이후부터는 전혀 발생하지 않으며 윈도우 2000만의 문제. 후대의 추가 최신 업데이트까지 다 받으면 어찌 될지 모르지만, 아무튼 SP4까지 가도록 이 문제는 고쳐지지 않았다. 2000만의 고질병으로 기록될 듯.

(이해를 돕기 위해 스크린샷을 첨부하자면, '위'가 '아래'로 바뀐다는 뜻이다. RGB(10,36,106)이 RGB(0,0,128)로 변경. 본인에게는 정말 바로 티가 나고 아주 거슬리는 버그였던 반면, 저 버그에 대해서 공감하는 사람은 주변에서 지금까지 전혀 보지 못했다. 윈도우 2000 쓰면서 스타도 띄워 본 적 없나??)

사용자 삽입 이미지

※ XP

1. 유저 인터페이스가 파격적으로 많이 바뀌었다 보니 초창기 SP0은 별 특이한 버그가 많았다.
스트링을 내장하고 있지 않은 리스트박스나 콤보박스는 LB_ADDSTRING 내지 CB_ADDSTRING 메시지로 아이템을 추가할 때 당연히 string을 NULL로 지정해도 괜찮은데, 새로운 비주얼 스타일(테마)이 적용된 컨트롤은 저렇게 하면 프로그램이 죽는 어이없는 버그가 있었다. -_-;; (비주얼 스타일 없는 옛날 컨트롤은 문제 없음)

95부터 2000/ME까지 아무 탈 없던 코드가 유독 XP에서만 문제를 일으킨 것. 과거 <날개셋> 한글 입력기 2~3.x 시절에 윈도우 XP (sp0)에서 일부 제어판 UI가 뻗던 문제는 이 문제 때문이었다. 매우 황당한 버그이기 때문에 이 문제는 SP1에서 곧바로 고쳐졌다.

2. XP부터는 응답이 없이 죽은 윈도우는 대책 없이 배째라 있는 게 아니라, 최소한 창의 이동과 강제 닫기는 가능한 일명 고스트 윈도우를 그 프로그램의 원래 윈도우를 대체하여 잠시 보여주는 기능이 추가됐다. 그래, 만든 취지는 좋다.

그런데.. 최대화되어 있던 프로그램 창이 한동안 응답이 없어서 고스트 윈도우가 됐다가... 다시 돌아와서 깨어나면,
그 창의 최대화 이전의 위치와 크기가 사라지고 창의 최대화를 해제해도 창 크기 자체가 최대화나 마찬가지인 상태로 남는 버그가 있었다. -_-
이 문제 역시 SP1을 전후한 시기에 고쳐졌다.

3. SP0은 무선 인터넷을 좀 하다 보면 lsass던가 뭐가 이상한 시스템 프로그램이 문제를 일으켜서 1분간 초 단위로 카운트다운을 한 후 운영체제가 재부팅되는 현상도 있었다. -_-;;
갑자기 그런 게 떠서 놀랐고, SP1만 설치해도 그 문제가 없어지는 것을 보고는 더 놀랐다. 도대체 SP0에서는 무슨 문제가 있었기에?

이외에 다른 사람들은 XP에서 시스템 차원에서 첫 도입된 TSF와 관련된 문제(ctfmon) 등 여러 버그를 찾아낸 듯하던데(해결책이라고 내놓은 게 '고급 텍스트 서비스 사용 안 함' ^^), 본인은 그런 건 모르겠고 저 세 가지 버그가 지금까지 기억에 남는다.
SP2는 저런 사소한 버그 해결 수준이 아니라 보안 관련 기능 추가가 즐비해서 단순 서비스 팩 같지가 않고,
SP3은 제대로 쓸 일도 없이 그 즈음에 비스타로 갈아타게 돼서 잘 모르겠다. SP2 정도만 해도 사실 상당히 안정화가 돼 있으니까.

※ 비스타

굉장히 오랜만에 출시된 만큼 엄청나게 높아진 사양, 그리고 디폴트로 적용돼 있는 UAC (사용자 계정 컨트롤) 때문에 뭇매도 많이 맞았다. 하지만 비스타는 객관적으로 상당히 잘 만든 OS이며, 7에 비해서 그 정도로 평가절하될 품질은 결코 아니다. 윈도우 98이 단순히 95+IE4가 결코 아닌 것과 같은 이치이다.

본인은 language bar (TSF 도구모음줄, 입력 상태 표시줄)를 task bar(작업 표시줄) 내부에 포함(embed, minimize)시키는 게 아니라 바탕화면에 동동 띄워 놓고 지낸다.
그런데 유일하게 비스타에서만 구경한 버그로는.. 응용 프로그램을 좀 사용하다 보면 이 language bar가 사라져 버리고 아마 내 기억이 맞다면 한글 입력도 안 되는 것.
내 컴만 그런가.. 왜 그런지 좀 성가시고 불편했다. 윈도우 시스템 디렉터리로 가서 ctfmon.exe를 재실행하면 사라졌던 language bar가 살아났다.

이것도 요즘은 구경을 안 하는 걸 보니, 다행히 서비스 팩을 설치하는 과정에서 고쳐진 것 같다.
엑셀 2007에서 유명하던 65535 곱셈 버그가 생각난다.
예전에 MS의 정책은 SP n은 SP n-1을 다 포함하는 형태였던지라, 최신 서비스 팩 하나만 갖고 있으면 됐다. 비주얼 C++ 6이라든가 윈도우 NT는 패키지 프로그램을 설치 후 최신 SP인 SP6만 깔면 끝이었던 것.

그런데 윈도우 비스타부터는 SP2를 깔려면 먼저 SP1부터 깔아야 한다. 매번 꽤 오래 시스템 파일 고치고 재부팅하고.. 불편하더라.
그래도.. 본인은 보안 업데이트는 귀찮아하는 편이지만, 서비스 팩은 그때 그때 깔 필요가 있다는 걸 체험 중. 왜냐하면 내가 현실적으로 직접 겪는 버그가 서비스 팩을 통해 곧장 해결된 경우를 꽤 자주 겪었기 때문이다.
듣기로는 비주얼 스튜디오 2010을 설치하려면 비스타조차도 SP1 이상이 필요하다.

아 그리고.. 윈도우 비스타 SP0은 인증 기간이 끝나면 대놓고 작동이 완전히 맘춰 버리는 유일한 운영체제이기도 했다. 기능 제한 모드가 되어, 인증을 받게 인터넷 접속이 가능한 웹브라우저 하나만 달랑 뜨고 다른 모든 기능을 사용할 수 없었다. 이 때문에 항의가 빗발쳤는지 SP1부터는 바로 사라지고 이는 후속작인 윈도우 7도 마찬가지. 화면이 주기적으로 까맣게 변하고 '이 제품은 정품이 아닙니다' 자막만 뜰 뿐, 동작 자체는 한다.

※ 7

콘솔에서, 한글을 조합 중이다가 비조합 문자를 “IME 차원에서” 삽입하면 조합 중이던 문자가 덧나는 버그가 있다. 이건 <날개셋> 문제가 아니라 MS IME에서도 나타나는 운영체제의 버그이다.
가령, "다"를 조합 중에 마침표를 누르면 "다."가 아니라 "다다."가 되는 것.

MS IME의 경우 두벌식일 때는 발생하지 않는다. 두벌식은 A~Z 사이에 배당된 한글 글쇠만 IME 차원에서 삽입하고 여타 숫자나 기호는 영문 자판과 동일한 방식으로 별다른 터치 없이 응용 프로그램으로 보내기 때문이다.
과거에 포트리스 space 버그를 비롯해서 MS IME가 유독 세벌식 자판에서만 발생하는 버그가 심심찮게 발견됐던 이유는 이런 동작 방식의 차이 때문이다. 세벌식은 아는 사람도 쓰는 사람도 거의 없다 보니 버그 발견이나 수정도 금방 금방 되지 않을 것이고.. -_-

이제 문자 입력 쪽 기능은 비스타 이후로 좀 안정화가 돼 있길 바랐건만, 또 뭘 건드려서 저런 버그가 생겼는지 모르겠다. SP1에서라도 당장 고쳐져 있길 기대한다.

Posted by 사무엘

2010/04/27 12:51 2010/04/27 12:51
,
Response
No Trackback , 6 Comments
RSS :
http://moogi.new21.org/tc/rss/response/254

과학의 날, 과학 노래

1. 과학 하는 마음으로 능률 있게 일하고
사람마다 손에 손에 한 가지씩 기술 익혀
부지런한 하루하루 소복소복 부는 살림
세상에 으뜸 가는 복된 나라 이루세

2. 과학으로 이치 찾아 새로운 것 발명하고
겨레의 슬기 모아 산업 크게 일으켜서
천 불 소득 백 억 수출 무럭무럭 크는 국력
세상에 으뜸 가는 힘 센 나라 이루세

3. 과학 하는 국민으로 기술 가진 국민으로
살림살이 늘려 가고 산업 크게 일으키면
나라의 힘 용솟음쳐 다가오는 평화 통일
세상에 으뜸 가는 민족 중흥 이루세


이 노래 아시는 분?
1970년대에 제정된 과학의 (날) 노래이다.
정말 "새벽종이 울렸네 새 아침이 밝았네" 만만찮게 그 시절 냄새가 아주 노골적으로 난다.

(박 정희는 교사 출신이고 음악· 미술 같은 예능에도 조예가 깊은 사람이었다. 본인은 개인적으로 <새마을 노래>-_-는 누구 대필이 아니라 그 사람이 진짜로 스스로 작사· 작곡했을 가능성이 높다고 생각한다.)

3절의 '민족 중흥' 하면 생각나는 거 없는지?
국민 교육 헌장에서 말고는 요즘 도무지 찾을 수가 없는 단어인데, 그때 '그분'이 저 표현을 정말 좋아했던 것 같다.
'국민 소득 1천 달러, 수출 100억 달러' 이런 가사는 정말, 철도의 노래로 치면 '지축을 흔드는 우렁찬 소리' 급의 옛날 추억이 돼 있다.

4월 19일은 우리나라에서 4 19 혁명일일 뿐만 아니라 찰스 다윈이 세상을 떠난 날이다.
(다른 훌륭한 과학자도 많은데 왜 하필 다윈이야.. -_-)
우리나라에서 과학의 날은 일제 강점기이던 1934년에 다윈의 기일을 기려 처음 시작됐다.
소파 방 정환 선생이 제정한 어린이날보다 약 10년 정도 늦게 시작된 것이다.
그러다가 과학 기술처가 발족된 4월 21일을 기려, 1968년부터 과학의 날이 재제정되었다. 참고로 국민 교육 헌장은 1968년 12월에 공표되었다.

본인은 저런 노래를 어떻게 아냐고?
엄청 어렸을 때 옛날 국민(초등)학교 음악 테이프에서 들었던 노래들은, 죽을 때까지 안 잊어버리고 기억하고 있어서이다. 머릿속 시스템 디렉터리에 known DLL로 등록됐다. ㅋㅋㅋㅋ
딱 초등학교에 입학할 때 이미 '읍니다'는 '습니다'로 바뀌어 있었고 국민 교육 헌장도 다 삭제되었지만, 그렇게 바뀌기 전의 교과서들을 본 기억은 있다. 정말 엄청난 옛날이 됐다.

본인은 딱히 수꼴 성향이거나 박통교-_- 신자는 아니다.
그러나 그 시절은, 이공계 과학 기술자가 "지금보다야" 정말 대접 받았으며, 긍지를 갖고서 마음껏 국가를 위해 일하던 시절이었을 거라고 생각한다.
그 반면 지금은? 현직 과학자들부터가 "내 자식 새끼는 절대로 이공계에 진학 안 시킬 거다" 그러는 시절이지 않은가!

  "그 어려운 살림에서도 박대통령은 과학 기술자들에게 파격적인 대우를 해줬다. 틈만 나면 과학기술자들 곁을 찾았다. 과로로 숨진 과학자들도 여러 명이나 됐다. 대전에 있는 국방과학연구소에는 그가 며칠씩 머물던 방이 하나 있었다. 그 방은 과학기술에 대한 그의 일선 지휘소였다. 그러나 그가 가고 난 지금까지 그 방을 찾는 사람은 아무도 없었다. 나머지 대통령들에겐 입으로만 과학이 중요했다."

아무리 지 만원 박사의 정치 성향이 싫다 하더라도 위의 내용만은 인정할 수밖에 없을 것이다.
특히 국방 과학 연구소는 정말 사기에 가까운 업적으로 지금까지 우리나라를 먹여 살리고 지키고 있는 곳 중 하나이다. 작년에도 과로로 순직한 분이 있었다!
나라가 잘 돌아가고 있을 때는 의료· 법조· 금융 같은 제로썸 산업 종사자가 아니라, 기술자가 늘 대접을 받았다.

  또 예루살렘에서 솜씨 있는 사람들로 하여금 기계(engine)들을 만들게 하여 망대와 보루 위에 두고 그것들로 화살과 큰 돌을 쏘게 하였더라. 그의 이름이 멀리 퍼졌으니 그가 놀랍게 도움을 받아 마침내 강하게 되었더라. (대하 26:15)

성경에서 역대기하 26장의 웃시야 왕의 업적을 읽어보면 정말 우리나라가 농업 개량을 하고 경제 개발하고 국방을 강화하던 1960~70년대 시절이 오버랩된다. 웃시야 왕은 교만으로 인해 비참한 최후를 맞이한 것도 박통과 일치하는 것 같다.

본인은 요즘 우리나라가 중산층이 몰락하고 빈부 격차 양극화가 심해지고 있다고 성토하는 사람에게 이렇게 묻는다. 그럼 이 땅에 중산층이 생기긴 언제 생겼냐고 말이다.
과학과 관련된 노래로 옛날에 드라마 카이스트 주제가가 생각나고, 대전 엑스포 주제가도 생각난다. 코리아나는 영 건전 가요 컨셉인 것 같다. 88 올림픽 주제가에 비해서 그리 잘 알려져 있지 않은 후자의 가사를 소개하며 글을 맺는다.


푸른 산들은 우리에게 말하네 고운 햇살 뿌려 달라고
이제 모두가 슬기로운 손길로 밝은 내일 꾸며 가 보자
아름다운 마음 마음 모여서 사랑으로 보살펴 주면
꿈이라고 생각했던 일들이 우리 앞에 펼쳐진다네 그 날은

우리 모두가 힘을 한데 모아서 끊임없이 달려 가 보자
하루하루가 다시 열릴 때마다 놀랄 일이 너무도 많아
우주 안에 감추어진 비밀을 차근차근 벗겨 가 보면
꿈이라고 생각했던 일들이 우리 앞에 펼쳐진다네 그 날은

그 날은 찾아오리라 그 날은 찾아오리라
미래의 물결 속에서 그 날은 찾아오리라 그 날은, 그 날은

Posted by 사무엘

2010/04/23 22:47 2010/04/23 22:47
, ,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/252

컴퓨터 구조를 공부하면서 배우는 기본 개념 중 하나는, ‘컴퓨터 내부에서 숫자가 표현되는 원리’이다.
부호 있는 정수는 소위 말하는 ‘2의 보수’ 형태로 표현되는데, 이것은 모든 비트가 1인 숫자는 -1이 되는 형태이다. 이런 방식을 쓰는 이유는 연산 회로를 설계할 때, 뺄셈을 덧셈의 변형만으로 매우 손쉽게 구현할 수 있는 체계이기 때문이다.

베이직 언어는 다른 언어들과는 달리 TRUE의 값이 -1인데, 그 이유가 바로 이런 컴퓨터의 구조와 관련이 있다. 베이직은 비트 연산자와 논리 연산자의 구분이 없기 때문이다.
0 아니면 1밖에 모르는 디지털 컴퓨터는 연속이나 무한 같은 개념을 표현할 수 없다. 숫자도 정수만 다루는 데 익숙하다. 그러나 현실 세계에서 발생하는 문제를 해결하려면 소숫점이 동반된 실수를 다뤄야 할 일도 매우 자주 발생한다.

소수를 표현하는 가장 간단한 방법은 소위 ‘고정소수점’이다. 가령 32비트 고정소수점의 경우, 정수와 완전히 똑같은 방법으로 숫자를 표현하되 실제로는 그 수의 의미를 정수를 16비트 크기만큼(65536) 나눈 것으로 인식하는 것이다. 즉, 수의 정밀도만 1이 아닌 1/65536으로 기계적으로 높아지는 셈.

고정소수점은 일단 덧셈· 뺄셈· 비교 연산을 정수와 완전히 동일한 방식으로 할 수 있어서 처리 속도가 매우 빠르며, 곱셈과 나눗셈을 할 때만 약간 주의해서 자릿수 정돈을 하면 되니 편하다. 실제로 일부 벡터 그래픽이나 글꼴 쪽 분야에서는 이런 고정소수점 방식이 잘 쓰이고 있다. 그러나 표현 가능한 수의 범위가 매우 심각하게 제한을 받기 때문에 범용성은 떨어진다.

자리수의 제약을 받지 않고 소수점을 좀더 자유롭게 표현하려면, 유효숫자와 자릿수를 따로 둘 필요가 있다. 그게 훨씬 더 실용적이다. 부동(floating)이라는 개념이 여기에서서 나왔다. 제일 큰 자리수의 숫자가 무엇이며 그 뒤에 0이 몇 개 붙느냐가 중요한 것이다.

이런 체계에서는 10.5에서 0.5는 제대로 표현할 수 있지만, 10000000.5에서 0.5는 손실될 가능성이 커진다. 그리고 한 숫자를 결국 두 수의 조합으로 표현해야 하므로, 각종 연산이 단순 정수보다 훨씬 더 느리고 힘들어진다.

옛날에는 이런 부동소수점 계산을 하드웨어 회로 차원에서 바로 해 주는 코(보조)프로세서가 별도로 존재했다. fdiv, fmul 같은 인스트럭션. 심지어는 제곱근이나 삼각함수 값까지 바로 구하는 명령이 있다!
하지만 시중에는 그런 게 없는 컴퓨터도 있다는 얘기이기 때문에, 1990년대에 상업용으로 쓰이던 어지간한 컴파일러들을 보면 소프트웨어적으로 부동소수점 계산을 흉내 내는(엄청 느리지만-_-) 코드를 추가할지를 지정하는 옵션도 있었다.

그런데 부동소수점을 표현하는 방식 자체가 통일돼 있어야 그 기준에 따라 코프로세서를 만들든지 말든지 할 수 있을 것이다. 그 표준 규격이 바로 IEEE754이다. 1985년에 제정되었다.

이 규격은 좀 정밀도가 떨어지지만 처리 속도가 더 빠른 32비트와, 용량이 넉넉하지만 역시 속도의 압박이 있는 64비트로 나뉜다. CPU 단위가 16비트이고 부동소수점을 소프트웨어적으로 처리하는 게 보편적이던 옛날에는, 아예 컴파일러 재량으로 소프트웨어적으로 구현한 48비트(6바이트-_-.. 파스칼에서 Real) 실수와 80비트(C/C++에서 long double) 실수도 존재하였으나 지금은 완전히 흑역사가 되었다. 요즘은 화면 픽셀 크기도 24비트는 존재하지 않으며 32비트이다. 죄다 컴퓨터가 처리하기 편한 단위로 그냥 확장된 듯하다.

제일 간단하게 말하자면, 32비트 실수에서는 1비트는 이 수의 부호를, 다음 8비트는 지수를, 다음 나머지 23비트는 유효숫자를 나타낸다. 64비트 실수에서는 그 비율이 1:11:52이다.
컴퓨터가 사용하는 부동소수점의 지수의 밑은 너무 당연한 말이지만 10이 아니라 2이다. 따라서 2의 거듭제곱의 역수가 아닌 모든 소수들은 끝자리가 잘린 ‘순환소수’가 된다! 0.25, 0.125, 0.5 같은 수가 아닌 다른 모든 수들.. 0.1, 0.2, 0.3 이런 것들은 화면에서는 적당하게 근사되어 표현되었다 할지라도 실제로는 그 수의 100% 정확한 형태로 저장되지 않은 셈이다. 부동소수점의 한계를 분명히 알고 있어야 한다.

어쨌거나.. 2^23과 2^52에다 base가 10인 로그를 씌워 보면 32비트 실수의 유효숫자 정밀도는 약 7자리, 그리고 64비트 실수의 정밀도는 약 15자리라는 걸 알 수 있다. 그리고 표현할 수 있는 자리수의 범위는 32비트는 약 38자리, 그리고 후자는 약 308자리이다(비트가 3개 더 늘어서 2^3인 8배가 더 늘었으므로). 소수점 밑으로도 그만치 내려갈 수 있다.

까놓고 말해 이런 공용체를 통해 부동소수점을 쉽게 해부할 수 있다.

union REAL {
   float fValue;
   struct {
      unsigned sign: 1; //부호
      unsigned expo: 8; //지수부
      unsigned mantissa: 23; //가수부
   };
};

공용체와 비트 필드가 존재하는 C/C++ 만만세. ㄲㄲ
단, 우리가 쓰는 인텔 CPU는 little endian이므로 sign, expo, mantissa 순이 아니라 반대로 mantissa, expo, sign으로 멤버 순서만 바꿔 주면 된다. 쉽죠?

그런데 지수부와 가수부 사이에 아무런 제약을 가하지 않을 경우 동일한 숫자를 여러 방법으로 표현할 수 있게 되어 문제가 생긴다. 4를 2의 2승, 4의 1승 이런 식으로 표현하듯이 말이다. 그래서 IEEE754는 가수부는 가장 큰 자리수의 비트값이 무조건 1인 것만 인정하게 하고 그 1은 명시적인 표기를 생략했다. 이를 ‘정규화’된 형태라고 한다.

거두절미하고, 32비트 부동소수점에서 구조체의 각 멤버로부터 부동소수점 값을 다시 얻어 오는 식은 다음과 같으므로 참고하자. 식에서 23과 24는 가수부의 자릿수 23비트와 관계가 있으며, 126은 지수부의 크기 8과 관계가 있다. 2의 8-1승보다 2 더 작은 값이다. 1<<23이 바로 생략된 최대 자리수인 셈이다.
그저 의미를 알 수 없는 블랙박스 같던 부동소수점이 좀더 친근하게 와 닿을 것이다.

pow(2.0, (double)( (int)a.expo-24-126))* ((1<<23)|a.mantissa) * (a.sign ? -1:1)

IEEE754에는 이외에도 무한대를 표현하거나 불능을 뜻하는 규격이 있다. 정수를 0으로 나누면 CPU 차원에서 바로 exception이 일어나지만 부동소수점은 에러는 안 나고 저런 특수한 숫자가 돌아온다.
또한 정규화를 해서 자리수를 강제로 늘리는 바람에 표현할 수 없게 된 일부 극히 작은 수를 별도로 표현하기 위해 내부적으로 심지어 ‘고정소수점’ 방식을 임시로 사용하는 규정조차 갖추고 있다. 마치 퀵 정렬이 작은 구간에서는 삽입 정렬을 사용하기도 하는 것처럼 말이다. 이에 대한 더 이상의 자세한 설명은 생략하겠다.

참고로,
1. IEEE754 부동소수점에는 구조적인 한계로 인해 0이 +0과 -0 이렇게 두 개 존재한다.
2. 역사상 최초의 전자식 컴퓨터로 일컬어지는(논란의 여지는 좀 있지만) 에니악은 10진법을 사용했다! 전자 신호 4비트(=16)로 10진법 숫자 하나를 표현했을 것이고 매우 비효율적으로 동작했을 것이다. 하지만 그 당시엔 이 기계로 탄도 계산도 하고 풍동 실험도 하고 심지어 일기 예보도 했었다.

Posted by 사무엘

2010/04/22 22:53 2010/04/22 22:53
, ,
Response
No Trackback , 7 Comments
RSS :
http://moogi.new21.org/tc/rss/response/251

<날개셋> 편집기를 오래 써 온 분들은 아마 아실 겁니다. 찾기/바꾸기 대화상자에 아주 교묘한 버그가 있습니다.
글을 쓰다가 Ctrl+F 또는 Ctrl+H로 이 대화상자를 한 수십 번 꺼내다 보면
정말 가끔, 아주 random한 확률로 엉뚱하게 explorer.exe가 죽거나, 편집기 프로그램이 죽거나 응답 불능 상태에 빠집니다. 윈도우 XP부터 비스타에서 모두 이런 증상이 나타나는 걸 확인했습니다. 에러 대화상자를 살펴보면 comctl32.dll이 뻗었다고 나옵니다.

이건 저도 원인을 알 수 없고 참 괴이하기 그지없는 버그입니다.
딱 원하는 때에 맞춰 재연은 절대로 할 수 없지만, 그래도 어디서나 언젠가는 100% 반드시 나타난다고 보장할 수 있는 현상이었지요.
발생 조건에 관한 한 최악의 버그입니다. 저는 무려 <날개셋> 3.x 시절부터 이것에 대해 알고 있었지만 디버깅할 엄두를 못 내고 있었습니다.

찾기/바꾸기 대화상자가 <날개셋> 편집기의 여느 대화상자들과 다른 점은 '탭 컨트롤'을 써서 찾기와 바꾸기 기능을 구분하고 있다는 점입니다. 혹시 이게 문제인가 싶어서 이번 기회에 아예 대화상자의 디자인을 바꿔 버렸습니다. 물론 5.53에는 아직 이게 적용이 안 돼 있고요.
5.53 이후로 다음 버전이 언제 나오게 될지 모르겠지만, 이렇게 하니까 이제는 저 문제가 없어졌는지 최소 몇 달간 살펴볼 예정입니다.

Posted by 사무엘

2010/04/19 07:35 2010/04/19 07:35
Response
No Trackback , a comment
RSS :
http://moogi.new21.org/tc/rss/response/249

철도에 고속철이 있다면 여객 항공기에는 초음속기가 있습니다. (정말 적절한 비유 ㅋㅋㅋㅋ)

1.

1903년이던가, 미국의 라이트 형제가 최초로 동력으로 움직이는 항공기를 발명한 후,
항공기는 1차, 2차 세계대전을 거치면서 전투기로도 등장하고 이내 여객용으로 가히 지구촌 시대를 열었습니다.
우리가 이용하는 대부분의 여객기는 최고 속도 순항 상태일 때 시속 850~900km (마하 0.9)쯤 되는 아음속기입니다. 이 정도로도 육지에서는 도저히 경험할 수 없는 빠른 속도이며, 사실 바람을 잘 탈 때면 아음속기도 시속 1200~1300에 도달해서 잠시 초음속으로 날기도 합니다. 그러나 속도에 대한 열망은 그것으로 모자라 초음속기의 개발을 부채질했습니다.

물론 자동차 중에도 초음속 자동차라는 게 있어서 주로 사막에서 시범 운행한 경우가 있습니다.
하지만 실용성은 거의 없죠. 그리고 그런 차들은 엔진도 일반적인 자동차의 4행정 기관이 아니라 제트 엔진을 쓰기 때문에 배기가스 배출, 연료 소모도 장난이 아닙니다. 여객 항공기는 대개 터보 팬 엔진을 쓰죠.

철도를 움직이는 핵심 동력원으로는 지하철과 고속철 모두 전기가 각광을 받고 있지만 비행기의 동력원은 역시 기름입니다. 그렇다고 해서 디젤-전기 방식은 아니고요. 항공유는 경유-중유 수준의 묵직한 디젤유는 아니고 휘발유에서 등유 사이뻘 되는 등급으로 알고 있습니다. 단지, 경주용 자동차용 연료에다 그러는 것처럼 옥탄가를 더욱 강화하고, 특히 영하 수십 도에 달하는 구간에서도 얼지 않도록 부동액 성분도 첨가된다고 합니다.

오늘날 실용적으로 운행되는 고속철들이 최고 시속 250~300km대입니다. 하지만 비행기는 활주로를 한창 지나서 날아오르기 직전에 이미 시속 300km대로 달리게 됩니다. 열차가 자꾸 자주 정차하는 건 싫지만 항공기가 이착륙하는 건 신나고 재미있습니다.

항공기는 고도의 유체역학 원리에 따라서 하늘로 뜨게 됩니다. 당연한 말이지만, 양 옆으로 날개도 폼으로 있는 게 아니라 치밀한 설계에 의해 넣은 것이죠. 그런 비행기들은 지구와 같은 공기가 없는 곳에서는 연료를 연소시킬 수 없기 때문에 날 수 없기도 하지만, 양력을 발생시킬 수 없어서 더욱 뜰 수 없습니다.
또한 반대로 말하면 우주선들은 어차피 지구 대기권을 나는 항공기와는 다른 방식으로 운항하기 때문에 날개가 필요 없습니다.

2.

전투기야 우리나라도 초음속기 개발에 성공했으니 더 말이 필요없지만,
초음속 여객기 하면 역시 영국과 프랑스 합작으로 개발되었던 콩코드가 거의 유일합니다. 잘 알다시피 음속의 2배를 조금 넘겼지요.
사실, 콩코드가 등장하기 전에 미국과 소련은 냉전 구도 하에 우주 개발 경쟁만 한 게 아니라 초음속 여객기 연구도 앞장서서 했습니다. 하지만 미국은 그런 건 만들어 봐야 경제성이 없다는 판단 하에 일찌감치 연구를 포기했습니다. 그 대신 아음속 여객기의 덩치를 더욱 키우는 연구를 계속했죠.

그 반면 소련은 콩코드보다도 먼저 사실, 세계 최초의 초음속기를 만들어내기는 했지만 상용화하지는 못했습니다. 이런 와중에 영국과 프랑스가 유럽의 항공 기술의 자존심을 걸고 막대한 비용을 들여서 공동 연구를 한 끝에 콩코드를 만들어 내고, 적자까지 감수하면서 나름 20년이 넘는 세월 동안 운행을 한 것입니다. 대서양을 건너 런던· 파리에서 미국 뉴욕 사이를 왕래했습니다.

콩코드가 첫 비행에 성공한 것은 1969년 3월로, 인간이 최초로 달에 가는 데 성공한 아폴로 11호 발사의 4개월 남짓 전입니다.
콩코드는 빠른 속도를 내기 위해서 많은 것을 희생해야 했습니다.
폭이 작고 복도가 매우 좁아져서 한 줄당 좌석이 기차나 버스 수준인 2x2입니다. (우왕!)
만석일 때 100수십 명 남짓밖에 탈 수 없어서 이는 결국 한 사람당 매우 비싼 운임으로 연결됩니다. 2003년경에 대서양 한번 건너는 편도 운임이 한국 돈으로 거의 900만~1천만 원.. 일반 아음속 항공기 일반실 운임의 10배가 넘었다고 합니다.

어마어마한 동력을 내야 하기 때문에 같은 거리를 날아도 연료도 더 많이 들고, 이륙도 더 빨라야 하고 타이어에 걸리는 부담도 더 크고, 뜰 때 더 가파르게 하늘로 올라야 했다고 합니다. 거기에다 성층권의 오존층 파괴 문제, 소닉 붐 충격파, 자국 영공 내에서의 초음속 비행에 대한 규제 등, 골치 아픈 요인도 많았습니다.

끝으로 또 생각할 게 있습니다. 비행기가 하늘을 나는 상공은 영하 수십 도에 이르는 저온이지만, 그 정도로 빠르게 날면 공기와의 마찰 때문에 기체 역시 100~200도나 되는 온도로 달궈집니다. 우주선이 지구 대기권으로 재돌입할 때 시뻘겋게 열 받고 달아오르는 것과 같습니다. 그렇기 때문에 초음속기는 단순히 엔진의 출력만 강한 게 아니라 열에도 강해야 하고 마치 철도 레일이 여름에 늘어나는 것처럼 어느 정도 신축 현상에도 대비하여 설계되어야 합니다.

3.

그럼에도 불구하고 초음속 여객기의 위력은 정말 대단했습니다.
마하 2.2의 속도로 날면서 예전에 8시간 가까이 걸리던 런던-뉴욕을 고작 3시간 반대로 단축시켰기 때문입니다. 생긴 것도 학처럼 정말 우아하게 생겼죠.

이거 아십니까? 콩코드는 지구가 자전하면서 지표면이 돌아가는 속도보다도 더 빨리 이동하는 인류 최초의 교통수단이었습니다. (우주선이나 로켓은 아예 지구를 떠날 때 쓰는 물건이므로 논외로) 그래서 정오에 런던을 출발하면 현지 시각으로 오전 11시 30분에 뉴욕에 도착할 수 있었습니다.
이를 이용해 그때 인류 역사상 초유의 엽기적인 프로젝트가 진행되기도 했습니다.

1973년 6월 30일에 개기 일식이 일어날 때의 일이었습니다. 이런 사건은 지구상에서는 잘 해야 5~7분 남짓한 시간 동안밖에 관측할 수 없으며 사실 이것도 굉장히 운이 좋은 경우입니다. 그런데 지구의 자전 속도보다 더 빠른 비행기가 발명되었으니, 비행기로 달의 그림자를 쫓아가면서.. 일식 장면을 계속 관측하는 게 어떨까 하는 엉뚱한 생각!

과학자들은 일식을 가장 잘 볼 수 있는 경로를 치밀하게 계산해 놓은 후, 그 비싼 콩코드 비행기를 무려 전세 내서 기내에 온갖 측정 장비들을 설치했습니다. 덕분에 하늘에서 개기 일식을 무려 70분이 넘는 시간 동안 관측할 수 있었습니다. 그 해 10월 15일에 오일 쇼크가 터지기 100일 정도 전의 일이었죠.
http://sodyssey.egloos.com/2323422.

4.

그러나 초음속 여객기는 대중화하기에는 아직 시기상조였는지? 콩코드 역시 운영상의 어려움과 적자에 시달렸습니다. 자존심이 있는데 당장 운항을 중단할 수는 없고 좀 애물단지 계륵처럼 됐죠. 그렇게 시간은 흘러서 20세기가 막바지에 이르고 콩코드의 내구 연한 30년도 임박하기 시작했습니다.

그러던 차에 2000년 7월, 대형 사고가 터지고 말았습니다.
프랑스 파리의 드골 공항에서 이륙하던 콩코드 4590편.
이륙하는 과정에서, 직전 항공기가 이륙하면서 떨어뜨리고 간 금속띠를 밟으면서 타이어가 쫙~ 찢어져 터지고, 그 타이어 조각이 연료탱크를 파손했습니다.
비행기는 이미 시속 300km V1 속도를 넘어서서 이륙을 중단할 수 없는 상태가 돼 있었고, 기체 뒷부분이 불길에 휩싸인 채로 하늘로 떴습니다.

연료는 양 날개 내부에 담겨 있었는데 그게 다 홀랑 타 버리니 날개가 남아나질 못했죠. 곧바로 양력을 잃고 실속 상태. 조종이 불가능해진 비행기는 고도 100미터를 채 못 오르고 저공에서 빙빙 돌다가 추락해 버립니다.
화재 때문이었는지 탑승객 전원 사망.
최첨단 초음속기에다 25년 가까이 무사고를 자랑했던 호화 여객기 콩코드의 위상이 크게 흔들리게 되었습니다.
사고 원인을 추적한 과정이 정말 대단하더군요. 추리 소설을 읽는 기분이었습니다.
http://blog.naver.com/toysher?Redirect=Log&logNo=50007967386

이 사고를 계기로 콩코드는 안전 기준도 더욱 강화되었지만 슬슬 운행 중단으로 기울어 갔고,
2003년 10월엔 모든 콩코드기가 운항을 중단하고 현역에서 물러나게 됩니다.
간간히 뉴욕-도쿄 간 초음속기가 새로 개발 중이라고 몇 년 전부터 소식은 들어 왔지만 그게 언제 다시 실현될지는 모르겠습니다.

Posted by 사무엘

2010/04/16 12:35 2010/04/16 12:35
, , ,
Response
No Trackback , 4 Comments
RSS :
http://moogi.new21.org/tc/rss/response/247

원에 대한 적분 외

원이란 2차원 공간상의 한 점에서 거리가 같은 점들의 집합으로 정의된다. 공간이 3차원으로 확장되면 구도 이와 같은 맥락으로 정의 가능하다.
이 정의에 따라, 먼저, 0..r 범위에서 반지름이 r인 사분원을 나타내는 방정식

  f(x) = sqrt(r^2 - x^2)

를 정의하자.
이 사분원의 호의 길이는 거리의 적분에 따라

  int(  sqrt( f'(x)^2 + 1 ) , x=0..r)

(f'(x)는 f(x)의 도함수. int는 짐작하듯이 0부터 r까지 x에 대한 정적분을 나타냄)
을 풀면 PI*r/2 가 된다. 사분원의 길이이므로 여기에다 4를 곱하면
반지름이 r인 원의 길이는 2*PI*r이 나온다.
위의 적분식에서 1은 당연한 말이지만 적분변수가 약분되어 1이 된 것이며, 그걸 역시 제곱한 값이기도 하다. 괜히 더해진 게 아니다. ^^;;

넓이는 그냥 f(x)를 적분하면 바로 구해진다.

  int( f(x), x=0..r)

의 값은 PI*r^2 /4 가 되고, 역시 4를 곱하면 반지름이 r인 원의 넓이는 PI*r^2이 된다. 적분을 실제로 풀기 위해서는 치환 적분 기법이 필요하다.

이제 3차원 세계로 가서 구의 부피를 구하면 어떨까?
반구의 단면은 역시 0부터 r까지 반지름 자체가 원의 방정식과 같은 무수한 원으로 이루어져 있으며 이것들을 적분하면 부피를 구할 수 있다. 어렵지 않다. 즉, 원의 넓이 PI*r^2에서 r 대신에 f(x)를 넣으면 된다는 소리.

  int( f(x)*f(x)*PI, x=0..r)

의 값은 2/3 * PI * r^3이 된다. 반구의 부피이므로 이것에다 2를 곱하면 4/3 * PI * r^3이 바로 반지름이 r인 구의 부피이다.

마지막으로 구의 겉넓이를 구해 보자.
여기서 사람들이 제일 많이 틀리는 게 뭐냐 하면, 넓이를 그대로 적분하면 부피가 되었듯이 원호 길이를 그대로 적분하면 겉넓이가 될 거라는 생각이다. 그런데 그렇게 하면 적분을 해석적으로 풀든, 심지어 100개 1000개로 구간을 아무리 많이 나눠서 컴퓨터로 계산을 해 봐도 정확한 값이 나오지 않는다! 실제값보다 더 작은 값이 나온다.

원의 넓이나 구의 부피처럼 각 구간에서의 함수값만이 중요하다면 구간 수를 무수히 늘림으로써 정확한 값으로 수렴이 가능하겠지만, 구의 겉넓이는 앞서 다뤘던 '길이'를 구하는 것과 일면 비슷한 개념이다. 내 자신의 값뿐만 아니라 인접한 구간과의 기울기라는 개념이 감안되어야만 정확한 적분값이 나온다.
그래서 2*PI*r뿐만 아니라 원호를 구할 때 쓰던 식이 첨가되어야 한다.

  int( 2*PI * f(x)* sqrt( f'(x)^2 + 1 ), x=0..r)

이 적분식의 값은 2*PI*r^2이 나오며, 역시 2를 곱하면 반지름이 r인 구의 겉넓이는 4*PI*r^2임을 알 수 있다.

덧붙이는 말

1. 1부터 100까지 일일이 덧셈을 할 필요가 없이 등차수열의 합을 구하는 식에 대입만 하면 100이 아니라 1000, 10000까지의 합도 손쉽게 구할 수 있듯.. 우리가 알고 있는 리만 적분도 굉장히 대단한 지식이다. 수천, 수만 개의 구간을 나눠서 일일이 함수값을 구하며 뺑이를 칠 필요 없이, 함수식의 부정적분을 구한 후 하한값과 상한값의 차이만 구하면 된다니, 놀랍지 않은가? 게다가 여기에다 부분 적분과 치환 적분의 위력까지 더해지면 초월 함수를 다루기도 더욱 수월해진다.

2. 사실 미분과 적분은 서로 다른 별개의 분야에서 출발했다. 접선 기울기하고 면적/부피는 언뜻 보기에 분야가 다른 것 같은데, 함수의 부정적분이 도함수의 역함수와 같다는 것이 증명되면서 미적분학이라는 한 학문이 태동한 것이다. 옛날엔 '극한이라는 걸 수학적으로 엄밀하게 정의하는 게 가능하나?' '이건 너무 사악한 사고방식이 아닌가?' 이런 걸 갖고 고민하던 시절이 있었다. 그저 기계적인 계산 테크닉(로피탈의 정리 같은. -_-)만 달달 외워서 점수 따기에는 이 분야는 너무나 깊이 생각하고 느껴야 할 게 많다. 본인 역시 학창 시절엔 그런 걸 별로 경험하지 못했다. 세상에 이런 개념을 처음 만든 사람은 무슨 생각으로 이런 걸 만들어냈을지를 곱씹어 보자.

3. 리만 제타 함수라는 게 있다. ζ(n)은 1/1^n + 1/2^n + 1/3^n ..... 의 극한이다. n=1인 경우에 속하는 조화 수열은 0에 수렴하지만, 그 합은 로그 스케일로 매우 느리게 발산-_-하긴 한다. (일반적으로 미분과 적분을 거치면 x의 지수가 1 늘어나거나 줄게 마련인데, 지수가 -1에 속하는 1/x은 부정적분이 예외적으로 생뚱맞은 ln x로.. =_=) 하긴, 숫자가 커질수록 소수의 개수도 로그 스케일급으로 발견되며 매우 드물어진다. 소수의 개수 역시 무한하다는 뜻이기도 하다. 숫자가 커질수록 졸라 찾기 힘들어지겠지만 말이다. -_-;;

이런 함수가 왜 근사한 이름까지 붙어 있는가 하면, n이 2 이상의 짝수일 때 ζ(n)의 값은 PI의 n승의 유리수배의 형태로 산출되기 때문이며, 더구나 이 함수는 소수의 분포와도 관계가 있기 때문이다. 이 엄청난 발견을 해 낸 사람은 불세출의 천재 수학자인 오일러이다. 특히 삼각함수의 테일러 전개와 방정식의 근의 관계를 이용하여, ζ(2) = PI^2 / 6 임을 최초로 알아내기도 했다. 따라서 그 수는 초월수라는 것 역시 덩달아 증명된 셈.

나는 증명을 뻔히 보고도 뭔 말인지 못 따라가겠던데, 사실 저것도 수학에서 가장 아름다운 방정식이라는 e^(PI*I) + 1 = 0만큼이나 그의 위대한 업적이 아닌가 생각한다. 파이, 삼각 함수, 루트, 해석학, 기하학, 복소수 등등등... 다 위로 올라가면 서로 구분이 없이 여기저기서 다 만난다는 뜻이다. 심하게 경이로운 사실이다!

Posted by 사무엘

2010/04/15 20:07 2010/04/15 20:07
, , ,
Response
No Trackback , 8 Comments
RSS :
http://moogi.new21.org/tc/rss/response/246

C++에서 A라는 클래스를 만들었다. 이 클래스는 앞으로 당신이 만들 거의 모든 클래스들이 상속 받을 아주 기본적이고 공통적인 기능을 갖추고 있다. COM으로 치면 IUnknown, MFC로 치면 CObject 같은 기능을 하는데, 여기서는 그 예로 자체적인 reference counting 기능을 내장하고 있다고 치자.

class A {
 int nRefCnt;
public:
 A(): nRefCnt(1) {}
 ~A() {}
 int AddRef() { return ++nRefCnt; }
 int Release() { int nt=--nRefCnt; if(nt==0) delete this; return nt; }
};

이제 당신은 A로부터 상속 받은 여러 클래스들을 만든다.

class B: public A {
public:
 int nAddVal;
 B(): nAddVal(2) {}
};

class C: public A {
public:
 int nExitVal;
 C(): nExitVal(3) {}
};

그런데 C++에는 다중 상속이라는 게 존재한다.
어쩌다 보니, A의 자식 클래스들 중 서로 다른 클래스를 골라서 이들의 기능을 다 물려받은 클래스를 만들고 싶어진다. (욕심도 참 많다!)

class D: public B, public  C {
public:
 int nLast;
 D(): nLast(4) {}
};

여기서 문제가 생긴다.
이 경우, D는 B와 C의 기능을 물려받는 과정에서, B와 C가 공동으로 소유하는 A는 두 번 상속받게 된다.
32비트 기준으로 obj의 멤버 배열 순서는 대략 "1, 2, 1, 3, 4" 정도가 된다.

D obj;
obj.AddRef();

이 코드의 실행 결과는 어떻게 될까?
고민할 필요 없다. 이 코드는 컴파일 자체가 되지 않을 테니 말이다. =_=
D라는 클래스에는 A의 nRefCnt라는 멤버 자체가 둘 존재한다.
그렇기 때문에 B 쪽에 속하는 nRefCnt를 건드릴지, C 쪽에 속하는 nRefCnt를 건드릴지 판단할 수 없어서 컴파일러는 모호성 오류를 일으키는 것이다.
클래스 가계도는 보통 tree 구조가 되는데 이 경우 엄밀히 말하면 cycle이 존재하게 된다. 이 cycle을 일명 '죽음의 다이아몬드'라고 부른다.

obj.B::AddRef() 내지 obj.C::AddRef()라고 구문을 바꾸면 컴파일 에러 자체는 없앨 수 있다.
그러나 이것은 미봉책일 뿐이지 문제를 본질적으로 해결하는 방법은 아닐 것이다.
이건 클래스 B와 C가 아무 공통분모 없이, 우연히 AddRef라는 껍데기만 동일하고 의미는 완전히 다른 함수를 제각기 갖고 있는 것과 다를 게 없는 상황이다.
근본적으로는 D라는 클래스는 비록 B와 C의 기능을 동시에 상속 받았더라도 A는 단 한 번만 상속 받게 하는 방법이 있어야 한다. 그게 가능할까?

그래서 C++은 '가상 상속'이라는 걸 제공한다.
일반적으로 B라는 클래스가 A라는 클래스로부터 상속을 받았다면, B라는 클래스는 내부적으로 A의 몸체 뒤에 자기 몸체가 덧붙는다. 따라서 B 클래스의 오프셋과 A 클래스의 오프셋 사이의 간격은 컴파일 시간 때 딱 결정이 되어 버리며 언제나 고정 불변이다.

그런데 B가 A를 상속 받으면서 A를 '가상'으로 상속하면, B 클래스로부터 A 클래스의 오프셋은 자기가 별도의 내부 멤버로 갖고 있게 되며, 컴파일 시점이 아니라 실행 시점 때 동적으로 바뀔 수 있게 된다. 기반 클래스가 특수한 처리를 하는 게 아니라, 상속을 받고 싶어하는 자식 클래스가 상속을 특수한 방법으로 받아야 한다.
그래서 위의 네 클래스 A~D 중, 죽음의 다이아몬드를 해소하기 위해서는 B와 C가 A를 virtual로 상속 받게 하면 된다.

class B: virtual public A { ... };
class C: virtual public A { ... };

이 경우 B와 C는, 기반 클래스인 A가 자신과 메모리 상으로 굳이 연속적으로 이어져 있지 않더라도, B나 C 자신이 스스로 갖고 있는 부가 정보를 통해 기반 클래스인 A의 위치를 추적할 수 있다.

클래스 C만 갖고 생각하는 경우, 당연히 메모리 상으로는 A와 C가 바로 따를 것이고, C 내부에 있는 A의 포인터는 자기 바로 앞을 가리키고 있을 것이다.
하지만 클래스 D는 멤버가 ABCD와 같은 순으로 쫙 배열될 수 있으며, A와 C 사이에 B 같은 다른 클래스가 있을 수 있다. 그래도 B와 C가 A를 공유할 수 있게 된다. 공유를 하려고 이 지저분한 짓을 자처한 것이다.

자, 그럼 가상 기반 클래스의 구현 비용은 어느 정도 될까? C++에서

ptr->Function(a, b);

이라는 문장이 있고 Function이 virtual이 아닌 일반 클래스 멤버 함수라면, 위의 코드는 C 언어 문법으로 표현했을 때 대략

Function(ptr, a, b);

이 된다. 즉, this만 암묵적으로 추가되고 일반 함수와 완전히 똑같은 형태이다. 가장 간단하다.
하지만 Function이 가상 함수라면,

ptr->functbl->Function(ptr, a, b);

과 같은 꼴이 되고 오버헤드가 꽤 커진다. 우리 멤버가 가리키는 공용 가상 함수 테이블로 가서 거기서 함수 포인터를 참조하는 셈이다.
그렇다면 Function이 ptr이 가상으로 상속 받은 기반 클래스의 비가상 멤버 함수라면,

Function(ptr + ptr->baseptr, a, b);

정도. 가상 함수 정도는 아니지만 그래도 this 포인터의 위치 계산을 위해서 두세 개의 명령 오버헤드가 추가된다.
일단 다중 상속이라는 개념 자체가 컴파일러 문법상의 단순 형변환일 뿐이던 typecasting을 굉장히 복잡하게 만들었다는 점을 알 필요가 있다.

그럼 Function이 가상 상속에다가 가상 함수이기까지 하면 어떻게 될까?
그래도 functbl을 찾는데 오버헤드가 더해지지는 않는다. 어차피 각 클래스의 함수 테이블에는 자기가 지금까지 상속 받은 모든 클래스의 가상 함수들이 누적 기록되어 있기 때문에, 함수 호출을 위해 여러 테이블을 돌아다니지는 않는다.

참고로 A에 가상 함수가 있고 B와 C가 이를 제각기 오버라이드를 했는데 D가 B와 C를 동시에 상속 받고도 그 가상 함수를 또 오버라이드하지 않았다면, 컴파일 에러가 난다. B와 C 중 어느 장단에 맞춰 춤을 추리요? C++ 컴파일러는 그 정도 모호성은 자동으로 지적해 준다. C++ 컴파일러 만들기란 정말 힘들겠다는 생각이 들지 않는가?

가상 함수, 가상 상속, 멤버 함수 포인터... =_=;;
오늘날 프로그래밍 업계에서 다중 상속은 굉장히 지저분하고 흉악한 개념으로 간주되어 금기시되고 있다. C언어의 전처리기, 포인터와 더불어 현대의 프로그래밍 언어에서는 찾을 수 없는 면모가 되고 있다.
여러 클래스의 기능이 한꺼번에 필요하면, 무리하게 상속으로 해결하지 말고 해당 클래스 개체를 '멤버'로 가지는 쪽으로 가라는 것이다.

다중 상속이라든가 가상 상속이 골치아픈 게 결국은 데이터 멤버들의 오프셋 계산 때문이다. 하지만 가상 함수만 잔뜩 만드는 것은 그 클래스 자체가 아닌 함수 테이블의 덩치를 대신 키우는 것이고 클래스 자체는 가상 상속 같은 복잡한 테크닉을 필요로 하지 않기 때문에, 대다수 현대 객체 지향 언어들은 '인터페이스'라는 개념을 도입하여 이것으로 다중 상속의 기능을 어느 정도 대체하고 있다.
사실, C++의 각종 어려운 OOP 개념을 실제로 구현하는 데 비용이 얼마나 드는지를 잘 이해하고 있는 것만으로도 상당한 수준의 프로그래밍 내공을 쌓을 수 있다!

Posted by 사무엘

2010/04/14 17:19 2010/04/14 17:19
,
Response
No Trackback , 4 Comments
RSS :
http://moogi.new21.org/tc/rss/response/245

작곡가 안 지홍 씨

앞의 글을 쓰면서 인터넷 서핑으로 자료를 찾다가.. 아주 놀라운 사실을 발견하여 추가로 글을 남긴다.

무려 라틴어 가사 코러스가 나오는 MBC 드라마 <제 5공화국>의 주제가는 안 지홍 씨가 작곡했다. 그럼 작사는? 유명한 다른 문학 작품 구절에서 따오거나 설마 라틴어로 직접 작사를?? ㅎㄷㄷㄷ
게다가 이 사람은 1995년에 방영했던 <제 4공화국>의 주제가도 작곡하고 1993년의 <제 3공화국> 주제가도 작곡했다! 현대사 정치 드라마 OST 작곡엔 아주 이골이 난 사람이구나! 모두 MBC 드라마임.

사용자 삽입 이미지
이것은 <제 5공화국> OST 도입부 멜로디를 대충 채보한 것이다. 한국어 몬데그린 가사와 함께. ^^;; Looking for You와 비슷한 상당히 빠른 템포이다.

사용자 삽입 이미지
이것이 <제 4공화국> OST의 도입부 멜로디이다. 템포는 5공화국보다 훨씬 느리지만, 도입부가 끝난 뒤에 바로 높은 라(A)음의 높은 괴성이 나오고 나중엔 클라이막스를 거친 후 ‘전땡!’ 같은 함성으로 끝난다는 점. 그리고 역시 정체를 알 수 없는 이상한 언어 가사의 장엄한 코러스라는 점은 두 곡이 매우 유사하다.
그렇기 때문에, 두 드라마는 10년에 달하는 긴 시간 간격이 있음에도 불구하고 OST는 동일 작곡자의 작품일 거라고 개인적으로 추측이 가능했다. 그리고 그 추측은 사실이었다.

사용자 삽입 이미지
이것은 <제 3공화국> OST의 도입부 멜로디이다. 가사는 없다. OST가 흘러나올 때 시꺼먼 배경으로 각종 정치인들의 진흙/금속 인형 형상이 쫙 나왔다가 사라졌는데, 이 모습이 어렸을 때 보기엔 꽤 섬뜩하고 무서웠다.
모든 악보는 본인이 그냥 기억에 의지해서 야메로 집어넣은 것임을 밝힌다.

안 지홍 씨가 누군지는 처음 듣지만, 무엇보다도 그의 기념비적인 과업은 바로..

1994년 여름, 당시 최고의 납량특집 드라마로 오늘날까지도 불멸의 명작으로 남아있는 의학 스릴러 M의 주제가 역시 이 사람이 작사· 작곡을 했다는 사실!
제목은.. <나는 널 몰라>이다.

내 영혼이 아파오네
세월은 고독을 고독은 침묵을 침묵은 미움을 기다리고 있는 걸
(이건 무슨 롬 5:3-4 같은 점층법도 아니고 뭐야..)
모르고서 시간은 흘러가네
침묵 속에 쌓여서 아무것도 하고 있지 않네 들리지 않아
어둠 속에 숨어서 아무것도 하고 있지 않네 보이지 않아
나는 널 몰라 (네가 누군지, 네가 무언지, 네가 왜 나를 찾아왔는지...!) 몰라~~!!

M은 낙태를 소재로 하여 엄청난 사회적 반향을 일으켰던 드라마이지 않던가? 아래의 성경 구절을 염두에 두고 저 노래 가사를 곱씹어 보라. 섬뜩하다. 직접 들어 본 사람만이 그 전율스러움을 안다.

영의 길이 무엇인지 또 아이 밴 여자의 태 속에서 뼈들이 어떻게 자라는지 네가 알지 못하는 것 같이 모든 것을 만드시는 하나님의 일들도 네가 알지 못하느니라. (전 11:5)

TV에서 방영될 때는 시간 관계상 1절만 나왔지만 정식 노래는 1절+간주+2절이 있었다. 간주 때는 M 특유의 변조된 악마 목소리와 으헤헤헤헤헤’ 흉악한 웃음소리까지 곁들어져, 공포 분위기를 더욱 고조시켰다. 서 태지 음반에 사탄의 메시지가 백워드 마스킹으로 녹음돼 있다고 사회적으로 이슈가 된 지 얼마 되지도 않던 시절이었을 텐데?

자, <제 n공화국>과 M 모두 짐작하셨겠지만 어김없이 단조이다.
안 지홍 씨는 뭔가 장엄한 한편으로 쓸쓸하고 암울한 느낌이 나는 OST 제작에는 정말 탁월한 재능이 있는 분 같다.
M 얘기까지 나왔으니 그런 의미에서 짤방 하나 첨가하는 걸로 글을 맺겠다.

‘착시’라고 치면 어김없이 나오는 그림이다. 언뜻 보기로는 그냥 아리따운 아가씨의 초상화인데, 눈을 뚫어지게 쳐다보면 OME (Oh my eye!) 공포물로 바뀐다고 함. 본인은 뭔지 잘 모르겠다.

사용자 삽입 이미지

Posted by 사무엘

2010/04/13 17:14 2010/04/13 17:14
, , ,
Response
No Trackback , 5 Comments
RSS :
http://moogi.new21.org/tc/rss/response/244

눈과 귀의 착시

※ 모호한 그림

사람의 두뇌는 눈과 귀로부터 오는 정보를 토대로 3차원 공간을 구성해 내는 탁월한 능력이 있다.
귀는 소리를 들을 뿐만 아니라 두 귀를 통해 이 소리가 어느 방향에서 나는지도 감지할 수 있으며,
눈 역시 두 눈으로부터 정교하게 합성된 영상을 통해 사물의 원근을 직감하고, 이를 토대로 평면 이미지로부터 3차원 공간을 인지하게 된다.

그런데 평상시에 그렇게 2차원 영상으로부터 3차원 공간을 재구성해 낼 때 쓰이는 고정 관념을 교란함으로써 온갖 착시를 만들 수 있다. 멀쩡하게 곧은 선을 휘어진 것처럼 보이게 만들 수 있고, 똑같은 물체의 크기를 서로 완전히 다르게 만들 수 있다. 원근이라는 것은 크기의 변화뿐만 아니라 색깔의 변화도 수반하는 경우가 많기 때문에, 색을 교란해서 동일한 두 색을 서로 다르게 보이게 하는 것도 얼마든지 가능하다.

이런 것보다 좀더 상위 계층으로 가서, 머리가 사물이나 글자를 인식하는 방식까지 교란이 가능하다. 이런 것들. 본인은 처음엔 '중의적인 그림'이라고 검색했는데 도무지 검색이 안 되었다. 역시 '착시'라고 찾아야 된다.

사용자 삽입 이미지

착시라기보다는 중의적인 그림의 예로 아주 잘 알려져 있다. 젊은 여성이 옆을 응시하는 모습일까, 아니면 주걱턱 노파가 전방을 주시하는 모습일까? ㅋ

※ 모호한 소리 (몬데그린)

눈에 이어 귀를 교란시켜 보자. 몬데그린이란, 인간의 정상적인 언어가 다른 언어의 환청-_-으로 둔갑하여 들리는 현상을 말한다. 간단한 예로, 군대에서는 군가도 워낙 야메로 배우다 보니 가사를 잘못 알아듣는 경우가 있다. "조국의 방패들이다"를 "조국의 깡패들이다"로 알아듣는다거나...
본인이 아는 대표적인 몬데그린으로는,

첫째, 일명 식섭송. 원조는 오스트레일리아의 어느 영어 팝송이다. 한국어 환청-_- 내용의 context를 제공하기 위해 어느 남성 나레이터가 나지막한 목소리로 나레이션을 곁들여 주는데, 이게 진짜 배 짼다. 유행한 지 벌써 10년도 더 됐지만, 그 당시 PC 통신에서 이걸 처음으로 들은 사람들은 정말 눈물 흘리면서 웃었다.
"안 불렀어(I met a man) 난 배 안 불렀어 식섭아(six feet tall) 그럼 못 써(full of muscles) ... 잊을 수 없는(he just smiled and) 개미와(gave me a) 배추만의 샌드위치"

둘째, 2차 세계 대전 당시에 독일 해군 군가로 알려진 노래.
"빨간 펜 파란 펜 뭘 바래야? 빨간 펜 야광펜 팔고 있다 ... 아는 게 힘 모르는 게 힘"
건장한 군인들이 아주 씩씩하게 필기구 판촉 활동-_-을 하는 모습을 생각하면 웃음이 작렬하지 않을 수 없다. ^^

셋째, 몇 년 전 히트 쳤던 <제 5공화국>이라는 드라마의 주제가.
"공익이 공익이 포쓰를 20번이나 혼자 다 해. 개XX XX 워 오예~ ... 전땡!"
드라마 주제가라는 특성상, 몬데그린 자막이 삽입된 동영상이 나돌면서 많은 인기를 끌었다. 가사도 뭔가 주인공을 패러디한 듯한 인상을 주는데, 그래도 당사자는 장군-_- 출신이지, 4급 공익 나부랭이는 아니다. ^^;;

정말 영락없이 한국어와 똑같이 들린다. 하지만 원래 언어는... 무려 라틴어.
원래 가사는 "비록 사람은, 사람은 (불의의) 역사를 용서(망각? 묵인? 은폐?)할지언정, 신은 그리하지 않을 것이다. 신이라면, 신이라면!" 이라는 굉장히 의미심장하고 섬뜩한 의미이다.

Posted by 사무엘

2010/04/13 09:21 2010/04/13 09:21
, ,
Response
No Trackback , 5 Comments
RSS :
http://moogi.new21.org/tc/rss/response/243

윈도우 운영체제가 인식하는 실행 파일 포맷인 PE(portable executable)의 헤더를 보면,
이 EXE/DLL이 실행되는 플랫폼(x86, x64, IA64 등등)이라든가, 이 실행 파일의 특성을 나타내는 플래그 등 여러 정보가 존재한다.
그런데 그 플래그 중에는 'Large address aware' 여부를 나타내는 플래그가 있다.
이건 무엇을 뜻하며, 왜 만들어진 것일까?

윈도우 NT는 도스의 잔재 없이 처음부터 순수 32비트로 개발된 운영체제이다.
32비트 공간에서는 최대 2^32 = 4GB 크기의 가상 메모리를 사용할 수 있는데, MS는 전통적으로 하위 2GB는 응용 프로그램이, 상위 2GB는 커널이 사용하는 구도로 운영체제를 설계했다.

그때는 램은커녕 하드디스크 용량도 4GB보다 훨씬 적던 시절. 그러니 그때 32비트는 가히 무한대에 가까운 공간이었으며, 메모리 분배를 어떻게 한다고 해도 이상할 게 없었다.
응용 프로그램은 언제나 하위 2GB만을 사용하다는 게 무슨 뜻일까?
포인터에서 32비트 크기가 다 쓰이는 게 아니라, 최상위 1비트는 절대로 1이 될 일이 없다는 말이다.

그래서 일부 잔머리 잘 굴리는 프로그래머들은 포인터에다가도 자신만의 1비트짜리 boolean 정보를 최상위 비트에다 얹고, 포인터를 쓸 일이 있으면 그 값을 잠시 제거한 후 사용했다고 한다. 흠좀무.

그런데 세상이 변해서 이제 램이 기가바이트급 스케일이 되었고, 32비트 공간만으로는 부족한 시대가 왔다. 본격적으로 64비트 시대가 도래하기 전부터 데이터베이스처럼 아주 memory-intensive한 프로그램을 돌리던 업계에서는, 유저와 커널을 2:2로 가르지 말고 3:1로 갈라서 응용 프로그램에다가 메모리를 좀더 많이 얹어 달라고 MS에다 끊임없이 요구했다. 그래서 MS는 '물리 주소 확장' 모드라는 걸 만들어 줬다.

사실, 커널도 메모리, 좀더 정확히 말하면 주소 공간이 의외로 많이 필요하다. 2:2도 오히려 부족한 감이 있다. 커널 코드를 얹고 각종 커널 오브젝트를 관리하는 메모리만 필요한 게 아니기 때문이다. 가상 메모리라는 시스템은 그 개념상 메모리를 관리하기 위한 메모리도 요구하는 법. 그와 관련되어 방대한 공간이 필요하며, 디바이스 드라이버를 얹고 돌리기 위한 메모리 등등도 따지면 결코 만만한 수준이 아니다.

3:1로 가르면 응용 프로그램이야 사용 가능한 메모리가 좀더 늘며, 종전에는 응용 프로그램이 한번에 약 1GB 남짓밖에 매핑을 못 하는 memory mapped file도 훨씬 더 큰 크기까지 확장할 수 있다. 하지만 만들 수 있는 프로세스/스레드 수가 감소하며 네트웍이라든가 운영체제의 전반적인 기능상의 한계가 매우 커지고, 운영체제가 이론적으로 관리 가능한 총 물리 메모리의 양도 줄어든다! 이 tradeoff를 반드시 잊지 말아야 한다.

그런데 문제는...
그렇게 3:1로 응용 프로그램의 메모리 주소를 확장하면...
드디어 최상위 비트가 1인 포인터 값이 응용 프로그램으로 오는 게 가능해진다는 것.
그렇다면, 예전에 놀고 있던 최상위 비트를 다른 용도로 활용하던 프로그램을 이런 확장 환경에서 돌리면.....;;; 더 이상의 자세한 설명은 생략한다.

그래서 호환성을 목숨처럼 1순위로 강조하는 MS는, 아무 프로그램이나 일방적으로 넓어진 포인터를 주는 게 아니라, 넓어진 포인터를 줘도 안전하다고 플래그가 따로 지정되어 있는 프로그램에 대해서만 제 기능을 다하도록 하는 정책을 선택했다. 그것이 바로 large address awareness이다. 이 플래그가 없이 빌드된 프로그램은 여전히 메모리를 2GB씩밖에 못 쓴다. 마치 윈도우 XP 이후에도, 별도의 매니페스트를 내장하고 있지 않은 옛날 프로그램들은 비주얼 스타일 테마가 적용되지 않는 것과 같은 맥락으로 말이다.

단, 이건 EXE에 한해서이다. DLL은 그런 선택의 권리가 없다. 확장 주소가 지원되는 EXE에 붙을 수도 있고 지원 안 되는 EXE에 붙을 수도 있으며, 어느 때건 동작을 잘 해야 한다. 따라서 DLL은 반드시 확장 주소를 지원하도록 작성되어야 한다.

본격적으로 64비트 환경이 되면서 확장 주소의 진정한 의미가 드러났다. 이제는 상위 1비트 정도가 아니라 아예 테라바이트급 메모리 주소에도 접근 가능해야 하며, 64비트 프로그램은 '확장 주소 지원' 플래그가 반드시 있어야 한다. 이 플래그가 없으면, 비록 x64 내지 IA64 아키텍처용으로 만들어진 64비트 프로그램이라 할지라도 포인터의 주소로는 여전히 무려 2GB 이내의 값만 들어온다. -_-
포인터 크기를 4바이트 int 크기로 하드코딩하고 제작된 무개념 프로그램을 최대한 쉽게 64비트로 포팅할 수 있게 배려한 것이다. 물론 이 역시 EXE에 한해서이지만 말이다.

large address aware 옵션은 비주얼 C++의 x86 플랫폼에서는 호환성 차원에서 디폴트로 꺼져 있다. 즉, 사용자가 별도로 옵션을 켜지 않으면, 2GB까지만 인식하는 프로그램을 만든다.
하지만 x64/IA64 플랫폼에서는 사용자가 별도로 이 옵션을 끄지 않으면 디폴트로 켜져 있으며, 코드가 2GB 정도가 아니라 4GB 이상의 공간도 안전하게 인식하는 것으로 간주한다. 둘이 묘한 차이가 있다는 것을 기억하자.

물론 굳이 램이 4GB가 아니더라도 64비트는 CPU가 한번에 정보를 처리하는 단위 자체가 더 크다는 점 하나만으로 32비트보다 대용량 데이터를 처리하는 성능이 더 뛰어나다. double 실수형을 하나 스택에 얹을 때만 해도 32비트에서는 CPU 명령을 최소 둘 이상 써야 하는데 64비트에서는 한 번만에 끝난다는 소리이지 않은가. 그렇기 때문에 램 용량이 32비트 크기를 초과하기 전부터도 64비트 프로세서가 개발되어 일부 제한된 영역에서 쓰이기도 했던 것이다.

잘 알다시피 64비트 윈도우는 과거 16-32비트가 그랬던 것처럼 그 정도로 지저분한 호환 계층은 제공하지 않으며, 한 프로세스 공간에 64-32비트 코드가 공존하는 것을 허용하지 않는다. 그래도 윈도우 핸들값은 여전히 32비트 범위 안에만 존재하며 32와 64비트가 값을 그대로 공유 가능하다는 게 신기하다. 하긴, 윈도우 9x에서는 윈도우 핸들값이 아예 16비트 범위에 있었지만 말이다. ^^ 썽킹이라는 말도 참 오랜만에 다시 듣는다.

Posted by 사무엘

2010/04/12 09:12 2010/04/12 09:12
, ,
Response
No Trackback , 9 Comments
RSS :
http://moogi.new21.org/tc/rss/response/242

« Previous : 1 : ... 206 : 207 : 208 : 209 : 210 : 211 : 212 : 213 : 214 : ... 230 : Next »

블로그 이미지

그런즉 이제 애호박, 단호박, 늙은호박 이 셋은 항상 있으나, 그 중에 제일은 늙은호박이니라.

- 사무엘

Archives

Authors

  1. 사무엘

Calendar

«   2026/08   »
            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          

Site Stats

Total hits:
3994595
Today:
974
Yesterday:
2195