엔트리 포인트

**엔트리 포인트**(entry point) 또는 진입점(進入點)은 운영 체제에서 컴퓨터 프로그램으로 **제어권**이 변경되는 것이며, 프로세서는 프로그램이나 코드에 진입해서 실행을 시작한다. 어떤 운영체제나 프로그래밍 언어에서, 초기 엔트리는 프로그램의 한 부분이 아니라 런타임 라이브러리의 한 부분이다. 즉 런타임 라이브러리가 프로그램을 초기화하고 프로그램에 진입한다. 다른 경우에는 프로그램이 진입 직후에 바로 런타임 라이브러리를 호출하고, 이것이 반환된 후에 실제 실행을 시작한다. 이것은 로드 타임에서 런타임으로의 전환이다.

간단한 레이아웃(흔히 스크립트 언어, 간단한 바이너리 실행 파일 포맷 그리고 부트 로더)에서는 시작점에서 실행을 시작한다. 또는 상대 주소나 절대 주소가 아니라 고정된 위치에 존재한다.

그 대신에 프로그램 실행은 프로그래밍 언어나 운영체제 등에 의해 정의된 관용명을 통한, 지정된 이름으로 시작될 수 있다. 많은 언어에서(특히 C) 이 지정된 이름은 `main`이라고 불리는 함수이다. 결과적으로 엔트리 포인트는 **main 함수**이라고 불린다.

## 사용
엔트리 포인트는 소스 코드부터 실행 파일까지 적용 가능하다. 그러나 일반적인 소프트웨어 개발에서, 프로그래머들은 단지 소스 코드에만 엔트리 포인트를 명시한다. 실행 파일에의 엔트리 포인트는 실제 운영 체제의 응용 프로그램 이진 인터페이스 (ABI)에 의존하며, (ABI에 의해 고정되지 않을 시에) 컴파일러나 링커에 의해 생성된다. 실행 불가능한 목적 파일도 엔트리 포인트를 갖고 있는데, 이것은 추후에 실행 파일의 엔트리 포인트를 생성할 때 링커에 의해 사용된다.

### 현재
현재 사용되는 대부분의 언어와 운영 체제에서 프로그램은 오직 한 개의 엔트리 포인트를 갖는다.

C, C++은 `main`이라는 이름의 함수이며, 자바에서는 `main` 이라는 이름의 정적 메소드이다. C#도 `Main`이라는 정적 메소드를 갖는다.

주요한 운영체제들에서 표준 실행 파일 포맷은 한 개의 엔트리 포인트를 갖는다. 유닉스와 유닉스 계열 그리고 리눅스에서 사용되는 ELF 파일 형식에서 엔트리 포인트는 ELF 헤더의 `e_entry` 필드에 명시되어 있다. GNU 컴파일러 모음 (gcc)에서 링커에 의해 사용되는 엔트리 포인트는 `_start` 심볼이다. 비슷하게 마이크로소프트의 PE 포맷에서 엔트리 포인트는 `AddressOfEntryPoint` 필드에 명시된다.

주목할만한 예외로서 안드로이드가 있다. 다른 대부분의 운영체제와 달리 안드로이드는 하나의 엔트리 포인트를 갖지 않는다.(`main` 함수가 없다.) 대신에 시스템이 실체화하고 필요할 때 실행할 수 있는 필수 요소를 갖는다.

## 종료 포인트
프로그램은 일반적으로 운영체제로의 반환이나 충돌 같은 구조화되지 않은 방식으로 언제든 종료될 수 있다. 스크립트 언어들은 일반적으로 프로그램의 끝에 도달할 때 종료될 수 있다. 그러나 바이너리의 경우 제어가 운영체제에 반환되거나 프로세스의 메모리에서 넘쳐서 메모리 접근 위반 시에는 운영체제에 의해 종료된다.

보통 프로그램에 종료 포인트가 하나만 존재하지는 않는다. 그러나 어떤 경우에는 런타임이 충돌되지 않았다는 가정 하에 단일 종료 포인트를 통해 항상 구조화된 방식으로 종료되게 할 수 있다. 이것은 명시된 종료 함수를 호출하거나 런타임 예외 또는 운영체제 시그널을 통해 `main` 함수를 리턴함으로써 수행된다.

## 프로그래밍 언어들
많은 프로그래밍 언어들에서 `main` 함수가 프로그램이 실행을 시작하는 곳이다. 이것은 프로그램 기능의 고수준적인 조직을 책임지고, 일반적으로 실행 시에 프로그램에 주어진 명령줄 인자들에 대한 접근권을 갖는다.

main 함수는 프로그램 시작 시 실행되는, 프로그래머가 최초로 쓴 함수이며, 런타임 환경(crt0 또는 동등한)에 포함된 시스템 명시적 초기화에 의해 직접적으로 유발된다. 그러나 어떤 언어들은 C++ 글로벌 객체들의 생성자처럼 main 실행 전에 사용자가 쓴 함수들을 실행할 수 있다.

스크립트 언어 같은 다른 언어들에서 실행은 간단히 프로그램의 시작점에서 시작된다.

### C와 C++
C와 C++에서, main 함수의 함수 프로토타입은 아래와 같은 형식이다.

```c
int main(void);
int main();

int main(int argc, char **argv);
int main(int argc, char *argv[]);
```

파라미터의 `argc`, 명령줄 라인 개수, 그리고 `argv`, *인자 벡터* 는 각각 프로그램의 명령 줄 인자의 번호와 값을 받는다. `argc`와 `argv`의 이름들은 C에서는 어떠한 유효 식별자일 수 있지만 이러한 이름을 사용하는게 관행이다. 다른 플랫폼 의존적인 형식들도 C와 C++ 표준에서 허용되지만, C++에서는 리턴 타입이 항상 `int`여야 한다. 예를 들면 유닉스와 마이크로소프트 윈도우는 프로그램의 환경을 받는 세 번째 인수를 갖는다.
```c
int main(int argc, char **argv, char **envp);
```

맥 OS X와 다윈은 실행 바이너리의 경로 같은 운영체제가 제공하는 정보를 네 번째 파라미터로 갖는다.

```c
int main(int argc, char **argv, char **envp, char **apple);
```

main 함수에서 리턴된 값은 프로세스의 종료 상태가 된다. C 표준은 단지 두가지의 명시된 값을 의미하는데, `EXIT_SUCCESS`(전통적으로 0)와 `EXIT_FAILURE`가 그것이다. 다른 가능한 리턴 값은 구현 정의된다. 리턴 값이 프로그래머에 의해 정의되지 않을 시 컴파일러에 의해 `return 0;`이 `main()`함수의 끝에 추가된다. 이것은 C++ 표준에 요구되는 것이다.

엔트리 포인트는 `argc`가 양수이며 `argv[argc]`가 널 포인터라는 것을 보장한다. 관행적으로 명령 줄 인자는 `argc`에 의해 명시되며, `argv`는 만약 `argc`가 0보다 큰 경우에 첫 번째 요소로 프로그램의 이름을 포함한다. 즉, 만약 사용자가 "`rm file`"을 입력하면, rm 프로세스를 `argc = 2`와 `argv = {"rm", "file", NULL}`로 초기화한다. `argv[0]`은 `[[Ps (유닉스)|ps]]`, `top` 등에서 보이는 프로그램의 이름이다.

`main()` 함수는 특별한 점이 있는데, 보통 모든 C와 C++ 프로그램이 이것을 정확히 한 번 정의되어야 하기 때문이다.

만약 정의된다면, `main()`은 이것이 외부 링크를 가진 것처럼 정의되어야 한다. 이것은 `static`나 `inline` 처럼 정의될 수 없다.

C++에서, `main()`은 글로벌 이름공간 (예를 들면 `::main`) 안에 있어야 하며, 오버로드될 수 없고, 멤버 함수일 수 없다. C와 달리 C++에서 `main()`은 재귀적으로 호출될 수 없고 자신의 주소를 가질 수 없다.

### 펄
펄에서는 main 함수가 없다. 문들은 위에서부터 아래로 실행된다.

명령 줄 인수들은 특수 배열 `@ARGV`를 통해 이용할 수 있다. C와는 달리 `@ARGV`에는 프로그램의 이름이 포함되어 있지 않다. 프로그램 이름은 `$0`를 사용하여 표기할 수 있다.

### PHP
PHP에는 "main" 함수가 없다. PHP 스크립트의 첫 줄에서 시작하면서, 함수 헤더로 감싸지 않은 모든 코드는 보이는대로 바로 실행된다.

## 주진입점
주진입점(主進入點)은 정보·통신분야에서 프로그램이 호출된 경우에 제어가 옮겨지는 위치를 가리킨다. 진입점은 1개의 주진입점과 지정된 수의 부진입점으로 이루어질수있다. 주진입점에 제어를 건네는 것은 그 프로그램이 본래 이름 또는 다른 예약된 이름으로 불릴 경우이나, 부진입점에 제어를 건네는 것은 다른 이름으로 불릴 경우에 한하게 된다.

## 같이 보기
* crt0
* 런타임 시스템

## 각주

## 외부 링크
* Hello from a libc-free world! (Part 1), March 16, 2010
* How main method works in Java

분류:제어 흐름