가변인자 포워딩 시키기 :: 2007/09/07 13:57


[마소 플러스]
C 프로그래밍 테크닉
가변인자 포워딩시키기
-------------------------------------
신영진 http://www.jiniya.net | 웰비아닷컴에서 보안 프로그래머로 일하고 있다. 시스템 프로그래밍에 관심이 많으며 다수의 PC 보안 프로그램 개발에 참여했다. 현재 데브피아 Visual C++ 섹션 시삽과 Microsoft Visual C++ MVP로 활동하고 있다. C와 C++, Programming에 관한 이야기를 좋아한다.
-------------------------------------

C 언어 함수의 가장 큰 특징 중의 하나는 가변 인자를 지원한다는 점이다. 가변 인자란 인자의 개수가 가변적이란 의미다. func란 함수가 가변 인자 함수라고 한다면 func(1), func(1,2), func(a,b,str) 등으로 호출할 수 있다. 이러한 특징을 가장 잘 활용한 대표적인 함수가 printf다.

<리스트 1>의 코드에 이번 달에 언급할 문제가 나와 있다. mysum은 단순히 인자를 realsum으로 전달하는 기능을 담당하고 있다. 이번 달의 문제는 mysum을 구현하는 것이다. <리스트 1>의 mysum처럼 구현하면 될 것 같지만, 이 코드는 컴파일되지 않는다.  realsum을 <리스트 1>과 같이 호출하는 것이 불가능하기 때문이다. 나머지 부분을 읽기 전에 이 문제를 어떻게 해결할 수 있을지를 한번쯤 고민해 보자.

<리스트 1> 다른 함수로 가변 인자 전달

문제를 해결하기 위해서는 가변 인자가 동작하는 구조에 대해 정확하게 이해할 필요가 있다. 가변 인자를 이해하기 위해서는 __cdecl 함수 호출 규약과 함수 호출에 스택이 어떻게 사용되는지에 대해 먼저 이해해야 한다(http://www.jiniya.net/lecture/techbox/callconv.html 참고). <리스트 2>에는 가변 인자에 사용되는 매크로의 구현 소스가 소개되어 있다. 이를 살펴보면 알 수 있겠지만 va_start, va_end, va_arg에는 사실 그다지 대단한 내용이 들어 있지 않다.

<리스트 2> 가변 인자 관련 매크로 구현 소스

가변 인자를 조작하는 매크로의 핵심은 va_list다. 이 인자로부터 모든 가변 인자를 구할 수 있기 때문이다. 따라서 문제를 해결하는 가장 손쉬운 방법은 va_list를 인자로 받아들이는 내부 함수를 만드는 것이다. 이렇게 해결한 코드가 <리스트 3>에 나와 있다. coresum 함수는 원래 realsum 함수가 가진 역할을 옮겨놓은 함수다. 이제 realsum, mysum 함수는 coresum 함수를 호출해 동일한 기능을 할 수 있다.

<리스트 3> va_list를 이용한 가변 인자 전달

앞의 해답의 경우에는 realsum 코드를 수정했기 때문에 우리가 처음 의도했던 정답이라고 할 순 없다. 그렇다면 realsum의 코드를 하나도 수정하지 않고 인자를 전달할 방법은 없을까? 정상적인 방법으로 할 순 없지만 앞에서 살펴본 가변 인자의 동작 원리와 약간의 어셈블리 지식을 결합하면 만들 수 있다. <리스트 4>는 이러한 방법으로 가변 인자를 통째로 전달하는 방법을 보여준다.

<리스트 4> 어셈블리를 통해 가변 인자를 전달하는 함수

<리스트 4>의 코드는 가변 인자가 정수라는 가정을 하고 있다. 만약 printf 류의 함수 인자를 포워딩시켜야 한다면 조금 더 문제가 복잡해진다. 넘어온 문자열로부터 인자의 크기를 계산해야 하기 때문이다.

네이버에 북마크 다음에 북마크 마가린 바르기 HanRSS에 북마크하기 이올린에 북마크하기 News2.0에 투고하기 del.icio.us에 북마크하기 Digg에 번역해 투고하기 dzone에 번역해 투고하기 붐바
이올린에 북마크하기(0) 이올린에 추천하기(0)
스폰서
글타래

  • 2주간 인기 글
  • 2주간 인기글이 없습니다.
Trackback Address :: http://www.jiniya.net/tt/trackback/599
Name
Password

Homepage
Secret
< PREV | 1| ... 61|62|63|64|65|66|67|68|69| ... 539| NEXT >