CPU가 아무리 빨라지고 온갖 개념의 프로그래밍 언어가 등장해도 현대의 컴퓨터는 종이테이프 머신에 기초를 두고 있다.
코드를 짜고 배포를 하고 디버깅을 하다보면 객체고 뭐고 아무리 포장을 해도 결국 소프트웨어란게 코드와 데이터의 스트림-종이테이프에 불과하다는 사실을 깨닫게 된다.
이걸 뼈저리게 느낀 첫 경험은 처음 멀티스레드로 네트워크 프로그래밍을 했던 2000년도였다. 여느 초심자들처럼 멀티 스레드 프로그래밍의 쓴맛을 톡톡히 맛보았다.
‘이 코드는 스레드 세이프한가? ‘
‘몇겹이나 감싼 이 클래스는 스레드 세이프한지 분석하는데 상당히 방해가 된다. 제거하자.’
‘호출단계를 줄이고 캡슐화된 레이어를 제거하자.’
‘어셈코드에 최대한 가깝게 만들고 보자. 아니 어셈으로 짜자.’
그렇게 디버깅을 하고 코드를 다시 짜고 보니 이건 그냥 C코드였다. 그렇게 네트워크 라이브러리를 다시 만들고나서야 제대로 작동하기 시작했다.
그 이후로 가장 기억에 남는 계기는 알파테스트때 유져로부터 날라온 300개의 덤프파일을 분석할때였다.
리턴값을 확인하려고 eax레지스터를 확인했고 어셈블리 코드의 일부를 보고 어떤 함수가 인라인되어서 사라진건지 추적했다. 특정 어드레스의 메모리맵을 보고 어떤 클래스의 인스턴스였을지를 조사했다.
객체? 클래스? 웃기는 소리다. 사실 객체가 어딨어. 말장난이다. ecx레지스터로 전달하는 포인터가 가리키고 있는 메모리가 객체라고 주장한다면 뭐..그렇게 볼수도 있겠지만…
사람이 아무리 추상화해서 ‘이런거다’ 라고 간주해봐야 컴퓨터는 그렇게 돌아가지 않는다.
난 지금도 리턴값은 32비트 아키텍쳐에서 4바이트, 64비트 아키텍쳐에서 8바이트로 제한한다. 어셈블리 코드를 볼때 eax레지스터와 rax로 리턴값을 확인하기 위함이다.함수에 전달하는 파라미터 사이즈도 반드시 4바이트 아니면 8바이트로 제한한다. 그래야 어셈코드 상에서 넘어온 인자값을 확인하기 편하다.
한줄의 코드가 경우에 따라 여러 가지 형태의 바이너리를 만들면 나중에 디버깅하기 어렵다. 고급언어 코드 -> 저급 언어 코드로 바뀔때 1:1 대응되는게 가장 디버깅 하기 좋다.
내가 C++컴파일러를 사용하면서도 C스타일을 고수하는 이유이다.
c에서 c++로 공부를 넘어갈 때 , 객체지향에 배우고 아리송 할 때
아니 이것도 코드는 위에서 아래로 읽고, 순서대로 읽는데 왜 절차지향이 아닌거지 ?
라는 생각이 들던데.. (이건 아닌가?)
컴퓨터는 그냥 튜링머신이다 라는 신념을 가지기도 했는데요, (서울대교양강좌 앞부분만 보고.. 갈수록이해안되서)
종이테잎머신은 어떤어린이가 지적유희로 고안해낸적이있을것이다 라고 생각합니다.
간단하게 본다면 간단한 종이테잎머신이 빛처럼빠른 전기를 만나 이뤄지는 걸 보면
교양책에서 본 복잡한일도 결국 작고 단순한 일들이 모인 것 이라는 구절이 생각나고,
만약 우리가 빛처럼 빠른속도로 이동한다면 컴퓨터는 쓸모없는게 아닌가
그럼 더 빠른걸 찾아야하나라는 라는 생각도 듭니다. 우주를 다니기엔 빛도 느리니까요
기초적인 지식이없지만 오늘 들린김에 예전에 봤던, 컴퓨터는 그냥 튜링머신아닌가?라는 생각을 글로 긁어준
글에 생각나는것을 적어봅니다.
좋아요좋아요
C++순혈주의자들은 펄쩍 뛰겠지만 C++이라고 해봐야 C와 근본적으로 다르지 않죠. struct에 코드를 넣을 수 있도록-그렇게 컴파일이 가능하도록-한 것을 포함해서 다양하게 장식을 한것에 불과하다고 생각합니다.
자동차 외관에 아무리 이것저것 바꿔도 근본적인 차의 세부 성능이 바뀌는건 아니죠.
좋아요좋아요
이런 첨언들이 공부할 때 의문이 들거나할때 들으면 더 확신이 설텐데 말이죠.
의문이 남거나 확신이 없는 공부는 반쪽자리공부..?
디스어셈블리를 같이 가르친다면 상당히 많은 부분이 해소될 것 같은 생각이 듭니다.
그래도 오늘 두고두고 볼 것을 올려주셔서 감사합니다.
좋아요좋아요