source

C에서 main() 메서드는 처음에 어떻게 호출됩니까?

gigabyte 2022. 8. 28. 09:47
반응형

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_mainlibc.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

반응형