프로그램 기동시에 “Runtime error 217″라는 에러가 발생하는 경우를 만나게 되면, 개발자로서는 상당히 당황하게 됩니다. 어떤 브레이크포인트를 잡을 곳조차도 없이, 밑도 끝도 없이 에러만 덜렁 발생하니까요. 게다가 더 진행도 안되고 프로그램은 그대로 끝나버립니다. 즉 프로그램이 시작도 되지 않은 상태에서 종료되어버리기 때문에 황당해집니다.
이 “Runtime error 217” 에러의 원인은, 일반적으로 프로그램 초기화시의 코드 에러 때문입니다. 더 정확하게는, 프로그램의 기본적인 예외처리가 동작하기 전에 예외가 발생하는 경우입니다. 가장 흔한 경우는, initialization 섹션에서 예외가 발생한 경우입니다.
델파이 애플리케이션의 기본적인 예외처리 루틴은 SysUtils에서 초기화가 이루어지는데, 만약 SysUtils 유닛이 초기화되기 전의 시점에서 뭔가 예외가 발생해버리면, SysUtils보다 더 아래 레벨인 System 유닛의 예외 처리 루틴을 타게 되는데요. 이 System 유닛의 예외 처리에서 바로 이 “Runtime error 217” 메시지를 내보내고는 Halt, 즉 강제 종료를 하도록 되어 있습니다.
initialization 섹션
앞에서 말한대로, 이 에러가 발생할 때 가장 크게 혐의를 둘 수 있는 곳은 initialization 섹션입니다. 따라서 프로젝트에 포함된 모든 유닛들에서 initialization 섹션이 있는지, 있다면 거기에 새로 추가한 코드가 있는지 확인해야 합니다.
SysUtils의 초기화 문제와 개발자 코드의 initialization 섹션과 관련이 있는 이유는 이렇습니다. 만약 프로젝트 전체의 uses들 중에서 불러지는 순서가 SysUtils보다 더 앞에 지정된 유닛의 initialization 코드가 실행되고 있는 시점에서는, SysUtils는 uses 되지 않은 상태라 당연히 예외 처리 루틴이 초기화되지 않은 상태입니다. 그래서 이 시점에서 예외가 발생할 경우 SysUtils의 예외처리 루틴으로 정상 처리되지 못하고 ‘Runtime error 217’ 에러가 나게 됩니다.
통상적으로 VCL 자체의 유닛들은 충분히 검증되었다고 볼 수 있으므로, VCL의 유닛이 아닌 개발자가 작성한 유닛이 uses에서 SysUtils보다 앞에 나열되어 있을 경우 의심의 대상이 됩니다.
작성한 유닛의 초기화 과정에서 꽤 복잡한 코드를 실행하는 경우에는 implementation 섹션에 함수나 프로시저로 만들고 그걸 initialization 섹션에서 호출하기만 하는 경우도 있으므로, 그런 경우라면 해당 함수까지 확인해봐야겠지요.
C++의 경우에도 델파이의 initialization 섹션에 해당하는 초기화 방법들이 있으므로, 만약 C++빌더에서 217 에러를 만났다면 이런 초기화 코드들을 확인해봐야 합니다.
윈도우7에서만 문제가 발생한다면
특히, 윈도우7이나 비스타에서 프로그램 기동시에 이 에러를 갑자기 만나고 당황하는 경우가 있는데요. 만약 동일한 프로그램이 윈도우XP에서는 이 에러가 나지 않는데 윈도우 7이나 비스타에서 기동시 이 에러가 난다면, 이것은 대부분 프로그램 초기화에서 권한이 부족한, 즉 권한 상승이 필요한 작업을 하려고 해서 예외가 발생했기 때문입니다.
윈도우7의 UAC로 인해 XP까지는 문제가 없던 코드가 문제가 생기는 경우로는, 권한이 없는 디렉토리에 파일을 쓰려고 했다든가, 권한이 없는 레지스트리 키에 값을 쓰려고 했을 경우 등이 있을 수 있습니다. XP까지는 이런 제한이 없었기 때문에 잘 돌아갔었지만 윈도우7/비스타의 권한 관리가 변경되어 생기기 시작하는 문제죠.
이것도 역시 initialization 섹션의 코드와 관련이 있습니다. initialization 과정에서 권한 상승이 필요한 동작이 있을 수 있기 때문입니다. 예를 들면 권한이 없는 디렉토리 경로의 파일을 write 하려고 한다든지 하는 코드가 권한상승이 되지 않은 일반 권한으로 실행되면 윈도우7 등에서는 예외가 발생하게 되는데, 그 코드가 initialization 섹션에 있었다면 역시 Runtime error 217이 발생하게 됩니다.
이런 경우는 의외로 종종 있습니다. 예를 들면 프로그램의 초기화 과정에서 Program Files 디렉토리 아래의 프로그램이 설치된 디렉토리에 있는 ini 파일에 뭔가 내용을 쓰려고 했다면 딱 이런 케이스에 걸리게 됩니다. 또 레지스트리에서 HKEY_CURRENT_USER 이외의 위치에 내용을 쓰려고 했다면 역시 권한상승이 필요한 동작이 됩니다. 이런 경우에 Runtime error 217이 발생합니다.
이런 케이스라면, 탐색기에서 해당 실행파일에서 오른쪽 클릭하여 “관리자 권한으로 실행”을 해보면 금방 확인할 수 있습니다. 이런 경우라면 관리자 권한으로 실행했을 경우에 217 에러 없이 정상 실행이 될 것이므로, 초기화중 권한이 더 필요한 코드를 실행했다는 의미가 됩니다.
외부 코드 uses 추가로 인한 경우
initialization 섹션에 추가한 코드로 인해 217 에러가 발생한다는 것은, 다시 말해 델파이나 C++빌더에서 다른 소스를 uses(링크)하기만 해도 이 에러가 날 수 있다는 의미도 됩니다.
예를 들면, 새로운 컴포넌트나 라이브러리를 갖다 써서 uses 됐는데, 그 컴포넌트가 윈도우7의UAC 문제에 대해 대비가 되어 있지 않은 구버전 소스이고 initialization 섹션에서 그런 코드를 썼다면 역시 217 에러가 날 것입니다.
이런 경우, 개발자로서는 별다른 코딩을 한 것도 아닌데 갑자기 에러가 발생하기 시작하므로 쉽게 원인을 찾기 어려울 수 있습니다. 따라서 자신이 initialization 섹션에 새로 추가한 코드가 없는데도 잘 동작하던 프로그램이 약간의 수정 후 217 에러가 발생하기 시작한다면, 별 생각없이 갖다 쓴 라이브러리 때문일 가능성이 높습니다.
UAC를 꺼버리거나 권한 상승으로 해결한다?
적지 않은 개발자와 프로그램 개발사들이 이 에러에 대한 해결책으로 사용자들에게 윈도우의 UAC를 끄라고 조언하고 있더군요. 윈도우 UAC의 취지 면에서 봤을 때, 프로그램의 동작을 위해 사용자에게 UAC를 끄라고 하는 것은 좋은 방법이 아닙니다. 특히 UAC를 꺼버린 문제로, 장기적으로 해당 사용자 PC에서 해킹이라든지 하는 문제가 일어났을 때 법적으로나 도의적으로 책임의 문제가 발생할 수도 있습니다.
이런 경우 개발자로서는 권한 상승을 하는 방법을 먼저 찾게 되는데, 사실 그보다 먼저 권한 상승을 하지 않고 해결할 수 있는 방법이 혹시 있는지 먼저 찾아보는 것이 좋습니다. 물론 꼭 권한 상승이 필요해서 피할 수 없는 경우가 더 많습니다만, 그래도 피할 수 있다면 피하는 것이 더 좋겠습니다. 권한 상승은 그냥 Yes 한번 누르면 끝나는 일이기는 해도 사용자로서는 아무렇지도 않게 무시할 정도의 일은 아닙니다.
또한 해당 프로세스에서 로드하는 외부 exe나 dll 등의 다른 모든 모듈들의 코드가 함께 권한이 상승되므로, 보안상의 이슈가 발생할 가능성도 얼마든지 있습니다. 따라서 꼭 필요한 경우가 아니거나 회피할 방법이 있다면, 무분별한 권한 상승은 하지 않는 편이 좋겠습니다.
프로그램 기동시에 Runtime error 217 이라는 에러가 발생하는 경우를 만나게 되면, 개발자로서는 상당히 당황하게 됩니다. 어떤 브레이크포인트를 잡을 곳조차도 없