C에서 main ()없이 프로그램 컴파일 및 실행


79

main()에서 함수 없이 다음 프로그램을 컴파일하고 실행하려고합니다 C. 다음 명령을 사용하여 프로그램을 컴파일했습니다.

그리고 컴파일러는 경고를 제공합니다.

알겠습니다. 문제 없습니다. 그런 다음 실행 파일 (a.out)을 실행하고 두 printf명령문이 모두 성공적으로 인쇄 된 다음 분할 오류가 발생 합니다.

그래서, 내 질문은, 인쇄 문을 성공적으로 실행 한 후 왜 세분화 오류가 발생합니까?

내 코드 :

산출:

Hello World...
Successfully run without main...
Segmentation fault (core dumped)

노트 :

여기서 -nostartfilesgcc 플래그는 링크 할 때 컴파일러가 표준 시작 파일을 사용하지 못하도록합니다.


37
나는 이것이 전혀 효과가 없다는 것에 놀랐다. 솔직히, 나는 링커에 의한이 처리가 잘못되었다고 생각합니다 (또는 적어도 나쁜 것) : 진입 점이 없었기 때문에 링커는 어떤 기능이든지간에 환각을주었습니다. Blech.
imallett

4
@imallett, 적어도 링커는 경고로 관심을 끌고 어떤 대체 조치를 취하고 있는지 설명하기에 충분히 친절했습니다! 그러나 이것이 단지 경고보다는 오류로 더 나을 수도 있다는 것이 맞습니다.
Toby Speight 2017

왜 메인을 사용하지 않습니까?
Pieter B

4
@PieterB-유니스에 대한 토론과 지나치게 관련이 없지만 Windows 프로그램의 진입 점이 반드시 필요한 것은 main아니지만 WinMain또는 wWinMain.
StoryTeller-Unslander Monica 2012 년

@StoryTeller는 실제로 Windows와 Linux 모두에서 임의의 진입 점을 설정할 수 있습니다. Linux의 ld경우 -e옵션이고 Windows의 MSVC 링커의 경우 /ENTRY옵션입니다.
Ruslan

답변:


131

프로그램 의 생성 된 어셈블리 를 살펴 보겠습니다 .

ret진술에 유의하십시오 . 프로그램의 진입 점이으로 결정되었습니다 nomain. 모두 괜찮습니다. 그러나 함수가 반환되면 채워지지 않은 호출 스택의 주소로 점프하려고 시도합니다. 그것은 불법적 인 접근이고 세분화 오류가 뒤 따릅니다.

빠른 해결책은 exit()프로그램 끝에서 호출하는 것입니다 (그리고 C11을 가정하면 함수를으로 표시 할 수 있습니다 _Noreturn).

실제로 함수는 main에서 반환 한 후의 반환 값으로 호출 main되므로 이제 exit함수는 일반 함수 와 거의 비슷하게 작동 main합니다.


6
프로그램에서 "반환"할 수있는 아키텍처 / OS 조합이 있다고 생각합니다. MS-DOS .COM 실행 파일? 어쨌든 우리는 구현 별 동작에 대해 깊이 알고 있습니다.
pjc50

4
@ pjc50-우리는 정말로 그렇습니다. OP의 경로는 Unix 변형을 제안했지만. 특정 아키텍처 및 지침 세트의 인기와 함께 생성 된 어셈블리를 답으로 제시하는 것이 편하다고 느꼈던 유일한 이유였습니다.
StoryTeller-Unslander Monica

1
관찰 일뿐입니다. -nostartfilesC 라이브러리를 사용할 수 없게 만들 수도 있습니다. C 시작 없이 C 라이브러리 함수 에 대한 후속 호출을 실행 하면 예기치 않게 실패 할 수 있습니다. 리눅스에서 당신은 컴파일한다면 -nostartupfiles그리고 -static당신은 프로그램이 잘못됩니다 발견 할 수 있습니다. 있습니다 C의 이 환경에서 작동하도록 설계되어 전면 초기화를 필요로하지 않는 MUSL 같은 라이브러리.
Michael Petch

22

C에서 함수 / 서브 루틴이 호출되면 스택이 다음과 같이 채워집니다 (순서대로).

  1. 인수,
  2. 반송 주소,
  3. 지역 변수,-> 스택 상단

main ()이 시작점이고, ELF는 먼저 오는 명령어가 먼저 푸시되도록 프로그램을 구성합니다.이 경우에는 printfs가 그렇습니다.

이제 프로그램은 반환 주소 또는 반환 주소없이 잘립니다. __end__실제로 해당 ( __end__) 위치 의 스택에있는 모든 것이 반환 주소 라고 가정 하지만 불행히도 그렇지 않아 충돌합니다.


4
스택 데이터의 순서가 C 표준에 정의되어 있습니까? 나는 그것이 시스템 아키텍처까지라고 생각
Délisson Junio에게

1
이것이 내가 ELF (실행 가능 및 링크 가능 파일 형식)를 언급 한 이유입니다. 이것은 필요한 OS에서 특정 ARCH 유형에 대해 교차 컴파일하여 생성됩니다.
Milind Deore

1
까다롭게하기 위해 스택이없는 시스템에서도 ELF 형식을 사용할 수 있습니다. 이러한 시스템의 한 예는 ELF 링커 파일을 생성하는 Codewarrior 컴파일러 가있는 Freescale RS08 입니다.
Lundin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.