C에서 main() 메서드는 처음에 어떻게 호출됩니까?
C 프로그램은 어떻게 시작하나요?
이 " " 를 합니다.main()
event ★★★★★★ 。
많은 Unix OS에서 사용되는 ELF(Executable and Linkable Format)는 엔트리 포인트주소와 INIT 주소를 정의합니다.여기서부터 OS가 종료된 후 프로그램이 실행됩니다.exec()
입니다._init
.init
된 주소인 '돌아가다'로 합니다._start
.text
★★★★★★ 。
C 컴파일러는 이러한 운영체제 정의 초기화 및 엔트리 포인트를 제공하는 모든 응용 프로그램에 표준 라이브러리를 연결합니다. 후, 그 는 「 」, 「 」를 호출합니다.main()
.
예시의 C 소스 코드를 다음에 나타냅니다.
#include <stdio.h>
int main() {
puts("Hello world!");
return 0;
}
부터부터objdump -d
:
Disassembly of section .init:
0000000000001000 <_init>:
1000: f3 0f 1e fa endbr64
1004: 48 83 ec 08 sub $0x8,%rsp
1008: 48 8b 05 d9 2f 00 00 mov 0x2fd9(%rip),%rax # 3fe8 <__gmon_start__>
100f: 48 85 c0 test %rax,%rax
1012: 74 02 je 1016 <_init+0x16>
1014: ff d0 callq *%rax
1016: 48 83 c4 08 add $0x8,%rsp
101a: c3 retq
Disassembly of section .text:
0000000000001060 <_start>:
1060: f3 0f 1e fa endbr64
1064: 31 ed xor %ebp,%ebp
1066: 49 89 d1 mov %rdx,%r9
1069: 5e pop %rsi
106a: 48 89 e2 mov %rsp,%rdx
106d: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
1071: 50 push %rax
1072: 54 push %rsp
1073: 4c 8d 05 66 01 00 00 lea 0x166(%rip),%r8 # 11e0 <__libc_csu_fini>
107a: 48 8d 0d ef 00 00 00 lea 0xef(%rip),%rcx # 1170 <__libc_csu_init>
1081: 48 8d 3d c1 00 00 00 lea 0xc1(%rip),%rdi # 1149 <main>
1088: ff 15 52 2f 00 00 callq *0x2f52(%rip) # 3fe0 <__libc_start_main@GLIBC_2.2.5>
108e: f4 hlt
108f: 90 nop
0000000000001140 <frame_dummy>:
1140: f3 0f 1e fa endbr64
1144: e9 77 ff ff ff jmpq 10c0 <register_tm_clones>
부터부터readelf -h
당신은 일치하는 진입점주소를볼 수 있습니다와 일치하는 진입 지점 주소를 볼 수 있다._start
:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x1060
Start of program headers: 64 (bytes into file)
Start of section headers: 17416 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 36
Section header string table index: 35
부터부터readelf -d
:
Dynamic section at offset 0x2dc8 contains 27 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000c (INIT) 0x1000
0x000000000000000d (FINI) 0x11e8
0x0000000000000019 (INIT_ARRAY) 0x3db8
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x3dc0
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x3a0
0x0000000000000005 (STRTAB) 0x470
0x0000000000000006 (SYMTAB) 0x3c8
0x000000000000000a (STRSZ) 130 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x3fb8
0x0000000000000002 (PLTRELSZ) 24 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x5e0
0x0000000000000007 (RELA) 0x520
0x0000000000000008 (RELASZ) 192 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000000000001e (FLAGS) BIND_NOW
0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
0x000000006ffffffe (VERNEED) 0x500
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0x4f2
0x000000006ffffff9 (RELACOUNT) 3
0x0000000000000000 (NULL) 0x0
당신은 INIT INIT 는의 주소로 동일한 경우, 다음의 주소와 같은 것을 알 수 있습니다를 볼 수 있다._init
..
에는 함수 포인터의 INIT_ARRAY에서 전체 어레이 또한 있다.INIT_ARRAY에는 포인터배열도 있습니다 함수.봐 봐objdump -s -j .init_array c-test
:
c-test: file format elf64-x86-64
Contents of section .init_array:
3db8 40110000 00000000 @.......
주소 0x3db8이 ELF 헤더의 INIT_ARRAY와 같은 것을 알 수 있습니다.
그 주소 0x1140(40110000에서-endian바이트 배열을 기억하)은 기능 주소 0x1140(40110000에서리틀엔디안 바이트 레이아웃을 기억함)이 함수입니다.frame_dummy
당신은 해체에서 볼 수 있다.분해에서확인할 수 있습니다.그 뒤 그러면호출이 됩니다 요구하고 있다.register_tm_clones
그리고 또 뭘 알고 있다.또 뭐가 있을지 누가 알겠어
초기화를 위한 코드 파일 crtbegin.o과 crtend.o(그리고 변형을 그 이름들)라는 이름의 집합에 있다.초기화 코드는 crtbegin.o 및 crtend.o(및 이러한 이름의 변형)라는 이름의 파일 세트에 있습니다.__libc_start_main
libc.so 에 접속해 주세요.6월 6일GCC를 사용하다stdin, stdout, global static dindin및 C 프 、 C 프양양양양양양 양양양양 양양양 。
다음 기사에서는 Linux에서의 기능에 대해 자세히 설명하고 있습니다(투표수가 적은 아래 답변에서 인용).http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html
Windows 의 기능에 대해서는, 다른 유저의 회답이 이미 기술되어 있다고 생각합니다.
결국 운영체제입니다.일반적으로 실제 진입점과 주요 기능 사이에는 약간의 매개체가 있으며, 이는 다음과 같이 삽입됩니다.
컴파일러 링커
「Windows 」:에는 PE라고 하는 .IMAGE_OPTIONAL_HEADER
에는 ""라는 필드가 .AddressOfEntryPoint
이것은 실행되는 파일 내의 첫 번째 코드 바이트의 주소입니다.
OS가 메인을 호출한다.재배치 가능한 실행 파일에는 메인 위치를 가리키는 주소가 있습니다(자세한 내용은 Unix ABI 참조).
그런데 누가 운영체제를 호출합니까?
「RESET」신호(전원 투입시에도 단언)의 중앙처리장치는, 소정의 주소(예를 들면, 0xffff)로 일부의 ROM 를 검색하기 시작합니다.
통상, 메모리 칩의 구성, 기본적인 하드 드라이브 드라이버의 로드등을 실시하는 BIOS 에의 점프 명령이 있습니다.다음으로 하드 드라이브의 부트 섹터를 읽고 다음 부트 로더를 시작합니다.이 부트 로더는 NTFS 파티션의 읽기 방법 및 커널 파일 자체의 읽기 방법에 대한 기본 정보를 포함하는 파일을 로드합니다.커널 환경이 설정되고 커널이 로드된 후 실행을 위해 커널이 로 점프됩니다.
모든 작업이 완료된 후 커널은 소프트웨어를 로딩할 수 있습니다.
http://coding.derkeiler.com/Archive/C_CPP/comp.lang.c/2008-04/msg04617.html
아마 당신의 질문에 대한 가장 좋은 정보는 아래 링크 http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html,에서 찾을 수 있을 것입니다.지금까지 제가 본 것 중 가장 좋은 것입니다.
운영체제는 C 런타임(CRT)에 포함되어 실행파일에 링크된 함수를 호출합니다.이것을 "CRT 메인"이라고 부르세요.
CRT 메인은 몇 가지 작업을 수행합니다.그 중 가장 중요한 것은 적어도 C++에서는 글로벌 C++ 클래스의 배열을 실행하고 그 컨스트럭터를 호출하고 main() 함수를 호출하여 셸에 반환값을 제공하는 것입니다.
Visual C++ CRT 메인은 메모리가 기능하는 경우 몇 가지 작업을 더 수행합니다.Debug CRT를 사용하여 메모리누전이나 부정한 접근을 검출하는 경우 중요한 메모리할로케이터가 설정됩니다.또, 부정한 메모리액세스나 그 외의 크래시를 검출해 표시하는 구조화 예외 핸들러내의 메인을 호출합니다.
이미 게시된 답변 외에 전화도 가능합니다.main
네 자신.일반적으로 이것은 난독화된 코드 전용으로 남겨진 잘못된 생각입니다.
언급URL : https://stackoverflow.com/questions/3469955/in-c-how-is-the-main-method-initially-called
'source' 카테고리의 다른 글
수평 스크롤바가 없는 vue-multiselect 드롭다운리스트 (0) | 2022.08.28 |
---|---|
행렬 곱셈: 행렬 크기가 작거나 타이밍 차이가 큽니다. (0) | 2022.08.28 |
구성 요소 태그 내부는 알 수 없지만 구성 요소 태그 외부는 알 수 없는 "알 수 없는 사용자 지정 요소" 경고 (0) | 2022.08.28 |
vuejs 템플릿 내에서 스타일 태그를 사용하고 데이터 모델에서 업데이트 (0) | 2022.08.28 |
VueJs - 전환에 따라 div 색상 변경 (0) | 2022.08.28 |