추상화의 허상

CPU가 아무리 빨라지고 온갖 개념의 프로그래밍 언어가 등장해도 현대의 컴퓨터는 종이테이프 머신에 기초를 두고 있다.
코드를 짜고 배포를 하고 디버깅을 하다보면 객체고 뭐고 아무리 포장을 해도 결국 소프트웨어란게 코드와 데이터의 스트림-종이테이프에 불과하다는 사실을 깨닫게 된다.

이걸 뼈저리게 느낀 첫 경험은 처음 멀티스레드로 네트워크 프로그래밍을 했던 2000년도였다. 여느 초심자들처럼 멀티 스레드 프로그래밍의 쓴맛을 톡톡히 맛보았다.

‘이 코드는 스레드 세이프한가? ‘
‘몇겹이나 감싼 이 클래스는 스레드 세이프한지 분석하는데 상당히 방해가 된다. 제거하자.’
‘호출단계를 줄이고 캡슐화된 레이어를 제거하자.’
‘어셈코드에 최대한 가깝게 만들고 보자. 아니 어셈으로 짜자.’

그렇게 디버깅을 하고 코드를 다시 짜고 보니 이건 그냥 C코드였다. 그렇게 네트워크 라이브러리를 다시 만들고나서야 제대로 작동하기 시작했다.

그 이후로 가장 기억에 남는 계기는 알파테스트때 유져로부터 날라온 300개의 덤프파일을 분석할때였다.
리턴값을 확인하려고 eax레지스터를 확인했고 어셈블리 코드의 일부를 보고 어떤 함수가 인라인되어서 사라진건지 추적했다. 특정 어드레스의 메모리맵을 보고 어떤 클래스의 인스턴스였을지를 조사했다.

객체? 클래스? 웃기는 소리다. 사실 객체가 어딨어. 말장난이다. ecx레지스터로 전달하는 포인터가 가리키고 있는 메모리가 객체라고 주장한다면 뭐..그렇게 볼수도 있겠지만…
사람이 아무리 추상화해서 ‘이런거다’ 라고 간주해봐야 컴퓨터는 그렇게 돌아가지 않는다.

난 지금도 리턴값은 32비트 아키텍쳐에서 4바이트, 64비트 아키텍쳐에서 8바이트로 제한한다. 어셈블리 코드를 볼때 eax레지스터와 rax로 리턴값을 확인하기 위함이다.함수에 전달하는 파라미터 사이즈도 반드시 4바이트 아니면 8바이트로 제한한다. 그래야 어셈코드 상에서 넘어온 인자값을 확인하기 편하다.

한줄의 코드가 경우에 따라 여러 가지 형태의 바이너리를 만들면 나중에 디버깅하기 어렵다. 고급언어 코드 -> 저급 언어 코드로 바뀔때 1:1 대응되는게 가장 디버깅 하기 좋다.

내가 C++컴파일러를 사용하면서도 C스타일을 고수하는 이유이다.


답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중