동료로부터 main()
함수 를 작성하지 않고도 C 프로그램을 작성하고 실행할 수 있다는 것을 배웠습니다 . 다음과 같이 할 수 있습니다.
my_main.c
/* Compile this with gcc -nostartfiles */
#include <stdlib.h>
void _start() {
int ret = my_main();
exit(ret);
}
int my_main() {
puts("This is a program without a main() function!");
return 0;
}
다음 명령으로 컴파일하십시오.
gcc -o my_main my_main.c –nostartfiles
다음 명령으로 실행하십시오.
./my_main
언제 이런 일을해야할까요? 이것이 유용한 실제 시나리오가 있습니까?
답변
기호 _start
는 프로그램 의 진입 점 입니다. 즉, 해당 심볼의 주소는 프로그램 시작시 점프 한 주소입니다. 일반적으로 이름의 함수 는 C 런타임 환경의 시작 코드를 포함하는 _start
라는 파일에서 제공됩니다 crt0.o
. 몇 가지 항목을 설정하고 인수 배열을 채우고 argv
거기에 몇 개의 인수가 있는지 계산 한 다음 main
. main
반환 후 exit
호출됩니다.
프로그램이 C 런타임 환경을 사용하지 않으려면 _start
. 예를 들어 Go 프로그래밍 언어의 참조 구현은 스택에 마법이 필요한 비표준 스레딩 모델이 필요하기 때문에 그렇게합니다. _start
아주 작은 프로그램이나 틀에 얽매이지 않는 일을하는 프로그램을 작성하고 싶을 때 자신 만의 것을 제공하는 것도 유용합니다 .
답변
main
프로그래머의 관점에서는 프로그램의 진입 점 이지만 _start
OS 관점의 일반적인 진입 점입니다 (프로그램이 OS에서 시작된 후 실행되는 첫 번째 명령).
일반적인 C 및 특히 C ++ 프로그램에서는 실행이 main에 들어가기 전에 많은 작업이 수행되었습니다. 특히 전역 변수 초기화와 같은 것입니다. 여기에 당신이 사이에 일어나는 모든 일의 좋은 설명 찾을 수 있습니다 _start()
그리고 main()
또한 주가 (아래 설명을 참조) 다시 종료 된 후입니다.
이를 위해 필요한 코드는 일반적으로 시작 파일에서 컴파일러 작성자가 제공하지만 플래그를 사용 –nostartfiles
하면 기본적으로 컴파일러에 다음 과 같이 알 수 있습니다. “표준 시작 파일을 제공하는 데 신경 쓰지 마십시오. 스타트”.
이것은 때때로 필요하며 종종 임베디드 시스템에서 사용됩니다. 예를 들어 OS가없고 전역 개체를 초기화하기 전에 메모리 시스템의 특정 부분 (예 : 캐시)을 수동으로 활성화해야하는 경우.
답변
다음 은 이전에 프로그램을 시작하는 동안 발생하는 일에 대한 좋은 개요입니다 main
. 특히__start
입니다 실제 진입 점 OS의 관점에서 프로그램에.
이 주소는 명령어 포인터 가 프로그램에서 카운트를 시작할 .
거기에있는 코드는 일부 하우스 키핑을 수행하기 위해 C 런타임 라이브러리 루틴을 호출 한 다음을 호출 main
한 다음 작업을 중단하고 반환 된 exit
종료 코드 main
로 호출 합니다.
사진은 천 단어의 가치가 있습니다.
추신 :이 답변은 SO가 도움이되는 다른 질문 에서 이식 된 것입니다.
답변
언제 이런 일을해야할까요?
프로그램에 대한 자체 시작 코드를 원할 때.
main
C 프로그램의 첫 번째 항목이 아닙니다. _start
의 첫 번째 항목이 아니라 커튼 뒤의 첫 번째 항목입니다.
Linux의 예 :
_start: # _start is the entry point known to the linker
xor %ebp, %ebp # effectively RBP := 0, mark the end of stack frames
mov (%rsp), %edi # get argc from the stack (implicitly zero-extended to 64-bit)
lea 8(%rsp), %rsi # take the address of argv from the stack
lea 16(%rsp,%rdi,8), %rdx # take the address of envp from the stack
xor %eax, %eax # per ABI and compatibility with icc
call main # %edi, %rsi, %rdx are the three args (of which first two are C standard) to main
mov %eax, %edi # transfer the return of main to the first argument of _exit
xor %eax, %eax # per ABI and compatibility with icc
call _exit # terminate the program
이것이 유용한 실제 시나리오가 있습니까?
당신이 의미한다면, 우리 자신을 구현하십시오 _start
:
예, 제가 함께 작업 한 대부분의 상업용 임베디드 소프트웨어에서 _start
특정 메모리 및 성능 요구 사항과 관련하여 자체적으로 구현해야합니다 .
의미하는 경우 main
함수를 삭제 하고 다른 것으로 변경하십시오.
아니요, 그렇게하면 어떤 이점도 보지 못합니다.