Joel On Software, 기본으로 돌아가기

Java Concurrency in Practice, 기본으로 돌아가기

소프트웨어 개발의 큰 그림은 층층이 쌓인 케이크 같다. 가장 높은 층에 소프트웨어 전략이 있고 아래에 .NET과 같은 아키텍처, 그아래 자바와 같은 소프트웨어 개발 제품이나 윈도우 같은 플랫폼을 생각할 수 있다. 좀더 아래 부분은? DLL? 객체? 함수? 바로 CPU다. 소프트웨어 개발에 있어 최저층에서 벌어지는 몇 가지 단순한 동작원리를 자세히 알지 못하거나 아예 잘못 알고 있기 때문에 문제가 생긴다.

궁전은 멋지게 지었지만, 기초 공사가 형편없다. 아래에 튼튼한 시멘트 판을 대신해 잡석을 깔았다고 가정하자. 겉보기에는 멋진 궁전인데 평평한 바닥에 놓은 욕조가 가끔가다 왜 삐걱대는지 도대체 알 수가 없다.

이처럼 기초 동작에 대한 이해가 필요하다는 것을 역설하고 있다.

예제로 C언어로 된 간단한 연습문제가 있다. C에서 문자열은 값이 0인 널 null 문자로 끝나는 몇바이트를 포함한다. C언어에서 문자열은 아래의 두가지 문제점이 있다.

1. 널 문자를 찾아서 문자열 끝까지 가보기 전에는 끝을 알아내는 방법이 없다.

2. 문자열 내부에는 어떤 0값도 포함할 수 없으므로, JPEG 그림과 같은 비정형 이진 자료 Binary Large OBject(BLOB)를 C 문자열 내부에 저장할 수 없다.

문자열 하나를 다른 문자열에 덧붙이는 함수인 strcat을 살펴보자

void strcat( char* dest, char* src )
{
while ( *dest ) dest++;
while ( *dest++ = *src++ );
}

위 함수는 널 문자를 찾은 뒤에서 부터 한 문자씩 짤라서 덧붙이고 있다.

이 함수는 커닝헌과 리치 시절에는 충분했을지 모르지만 한가지 문제점을 안고 있따. 러시아 페인트공 알고리즘을 사용하는 함수이기 때문에 성능 측면에서 최악의 성능을 보여 줄 수도 있다.

러시아 페인트공 알고리즘

  • 첫날 150M를 칠한 페인트공이 날짜가 지날수록 100M, 50M, 30M를 칠하게 됐따.
  • 문제는 길이가 늘어날수록 페인트통의 위치가 멀어지기 때문이다.
  • 페인트통을 시작점에 놓고 페인트칠을 한다고 가정했을때

strcat을 사용할 떄 첫 부분은 매번 빌어먹을 널 문자를 찾아 목적지 문자열을 헤매다녀야 하므로 strcat 함수는 필요이상으로 느리며 작업규모가 커지면 성능이 현저히 떨어진다.

몇몇 똑똑한 프로그래머는 이렇게 고친다.

char* mystrcat ( char* dest, char* src )
{
while ( *dest ) dest++;
while ( *dest++ = *src++ );
return --dest;
}

마지막 문자열의 index를 반환하는 것이다.

파스칼 설계자들은 이런 문제점을 미리 알고 있었으며 문자열의 첫 바이트에 개수를 저장하는 방법으로 이를 해결했다. 바로 이런 문자열을 파스칼 문자열이라고 한다.

또 왜 기억공간을 정확하게 계산해야 할까? char bigString[1000]; / 얼마나 할당해야 할지 알 수 없음 /

해커가 이러한 코딩을 본다면 손쉽게 오버플로우 해킹과 웜 바이러스 제작에 쓰이는 기본 기술을 활용할 수 있다.

출처 : 조엘 스풀스키, 『 조엘 온 소프트웨어』, 박재호 이해영 옮김, 에이콘(2005.4), 2장 인용.