ue4 - c++ 구조체 배열



main() 함수를 사용하지 않고 프로그램을 작성할 수 있습니까? (14)

$ cat > hwa.S
write = 0x04
exit  = 0xfc
.text
_start:
        movl    $1, %ebx
        lea     str, %ecx
        movl    $len, %edx
        movl    $write, %eax
        int     $0x80
        xorl    %ebx, %ebx
        movl    $exit, %eax
        int     $0x80
.data
str:    .ascii "Hello, world!\n"
len = . -str
.globl  _start
$ as -o hwa.o hwa.S
$ ld hwa.o
$ ./a.out
Hello, world!

실제로 실행 파일을 실행하는 커널은 내부 심볼에 대해서는 아무것도 모르고 실행 가능 이미지 헤더의 바이너리로 지정된 진입 점으로 전송합니다.

메인이 필요한 이유는 일반적으로 "메인 프로그램"이 실제로는 다른 모듈이기 때문입니다. 진입 점은 C와 어셈블리의 일부 조합으로 작성된 라이브러리 제공 시작 코드에 있으며 라이브러리 코드는 main 을 호출하기 때문에 일반적으로 라이브러리 코드를 제공해야합니다. 그러나 링커를 직접 실행하면됩니다.

C 모듈 1 을 포함하려면 ...

Mac:~/so$ cat > nomain.S
.text
.globl start
start:
        call   _notmain
Mac:~/so$ as -o nomain.o nomain.S
Mac:~/so$ cat > notmain.c
#include <unistd.h>

void notmain(void) {
  write(1, "hi\n", 3);
  _exit(0);
}
Mac:~/so$ cc -c notmain.c
Mac:~/so$ ld -w nomain.o notmain.o -lc
Mac:~/so$ ./a.out
hi

1. 또한 x86-64로 전환하려고합니다.

https://src-bin.com

나는이 질문을 인터뷰에서 계속 듣고있다.

main() 함수를 사용하지 않고 프로그램을 작성 하시겠습니까?

내 친구 중 한 명이 매크로를 사용하여 코드를 보여 주었지만 이해할 수는 없었습니다.

그래서 질문은 :

main() 없이 프로그램을 작성하고 컴파일하는 것이 실제로 가능합니까?


Answer #1

" main 사용하지 않고"는 main 내에 로직이 허용되지 않을 수도 있지만 main 자체가 존재한다는 것을 의미 할 수도 있습니다. 나는이 질문에 답을 얻었지만이 질문에 답을 얻지 못했기 때문에 또 다른 가능한 대답이라고 생각한다.

struct MainSub
{
   MainSub()
   {
      // do some stuff
   }
};

MainSub mainSub;

int main(int argc, char *argv[]) { return 0; }

여기서 일어날 일은 MainSub 의 생성자에있는 것들이 사용할 수없는 main 이 실행되기 전에 실행될 것이고, 당신은 그곳에 프로그램의 로직을 배치 할 수 있다는 것입니다. 물론 이것은 C ++가 아니라 C가 필요합니다 (질문에서 분명하지 않음).


Answer #2

C 또는 C ++ 코드가 실행되면 알려진 시작 주소에서 실행되고 여기의 코드는 런타임 환경을 초기화하고 스택 포인터를 초기화하며 데이터 초기화를 수행하고 정적 생성자를 호출 한 다음 main ()으로 이동합니다.

이 작업을 수행하는 코드는 링커가 빌드 할 때 코드와 연결됩니다. GCC에서는 일반적으로 crt0.s입니다. 상용 컴파일러를 사용하면이 코드를 사용할 수 없을 것입니다.

결국, 어딘가에서 시작해야하고 main() 은 그 위치의 상징적 인 이름이다. 개발자가 언어를 무엇을 부르는 지 알 수 있도록 언어 표준에 따라 지정됩니다. 그렇지 않으면 코드가 한 도구 체인에서 다른 도구 체인으로 이식 될 수 없습니다.

OS가 없거나 최소한 프로세스 로더 (임베디드 시스템은 종종 main () 이후 에 시작되는 RTOS 커널을 포함 함)의 의미에서 OS가없는 '베어 메탈 (bare-metal)'시스템 용 코드를 작성하는 경우 이론적으로 할 수 있습니다 런타임 시작 코드를 완벽하게 제어 할 수 있기 때문에 원하는대로 C 코드 엔트리 포인트를 호출하십시오. 그러나 그렇게하는 것이 어리 석고 다소 비뚤어 질 수 있습니다.

VxWorks와 같은 일부 RTOS 환경과 대부분의 응용 프로그램 프레임 워크는 main ()) 또는 이와 동등한 라이브러리 코드를 사용하여 사용자 응용 프로그램 코드보다 먼저 실행됩니다. 예를 들어 VxWorks 응용 프로그램은 usrAppInit ()에서 시작하고 Win32 응용 프로그램은 WinMain ()에서 시작합니다.


Answer #3

g ++을 사용하는 한 링커 옵션 -e 사용하여 엔트리 포인트를 변경할 수 있으므로 다음 코드 및 컴파일 명령을 사용하면 main() 함수없이 프로그램을 만들 수 있습니다.

#import <iostream>

class NoMain
{
public:
    NoMain()
    {
        std::cout << "Hello World!" << std::endl;
        exit(0);
    }
} mainClass;

noname.cpp 로 파일 이름을 noname.cpp 했으며 컴파일 옵션은 다음과 같습니다.

g++ nomain.cpp -Wl,-e,_mainClass -v

사실을 말하면, 코드가 왜 잘 작동하는지 이해하지 못했습니다. 나는 전역 변수 mainClass 의 주소가 NoMain 클래스의 생성자와 동일 mainClass 생각한다. 그러나, 나는 또한 나의 추측이 맞지 않을지도 모른다는 것을 말할 수있는 몇 가지 이유가있다.


Answer #4

그들은 독립적 인 구현을 위해 작성된 프로그램을 참조 할 수 있습니다. C ++ 표준은 두 종류의 구현을 정의합니다. 하나는 호스팅 된 구현입니다. 이러한 구현을 위해 작성된 프로그램에는 main 기능이 있어야합니다. 그러나 독립 실행 형 구현에서 요구하지 않으면 main 기능은 필요하지 않습니다. 이는 운영 체제 커널이나 운영 체제에서 실행되지 않는 임베디드 시스템 프로그램에 유용합니다.


Answer #5

그렇습니다. main을 사용하여 컴파일 할 수는 있지만 링크 단계를 통과 할 수는 없습니다.

 g++ -c noMain.cpp -o noMain.o

Answer #6

시작 지점이 main() 아닌 freestanding environment (임베디드 환경 OS 커널 등)에 프로그램을 작성하지 않는 한 불가능합니다. C ++ 표준에 따라 main()hosted environment 에있는 모든 프로그램의 시작점 hosted environment .

당 :

C ++ 03 표준 3.6.1 주요 기능

1 프로그램은 프로그램의 시작 부분 인 main이라는 전역 함수를 포함해야합니다. 독립적 인 환경의 프로그램이 주요 기능을 정의해야하는지 여부는 구현에 따라 결정됩니다. [참고 : 독립적 인 환경에서 시작 및 종료는 구현에 따라 정의됩니다. 스타트 업에는 정적 저장 기간이있는 네임 스페이스 범위의 객체에 대한 생성자 실행이 포함됩니다. 종료에는 정적 저장 기간이있는 객체에 대한 소멸자 실행이 포함됩니다.

freestanding Environment 이란 무엇입니까? Hosted Environment 이란 무엇입니까?
C ++ 표준에 정의 된 준수 구현에는 두 가지 종류가 있습니다. hostedfreestanding .

freestanding 실행 형 구현은 운영 체제의 이점없이 실행되는 프로그램 용으로 설계된 구현입니다.
예 : OS 커널 또는 임베디드 환경은 독립적 인 환경입니다.

운영 체제의 기능을 사용하는 프로그램은 일반적으로 hosted implementation 됩니다.

C ++ 03 표준 섹션 1.4 / 7부터 :

독립 실행 형 구현은 운영 체제의 이점없이 실행을 수행 할 수있는 구현이며 특정 언어 지원 라이브러리를 포함하는 구현 정의 라이브러리 세트를 보유합니다.

더욱이,
섹션 17.4.1.3.2 프리 스탠딩 구현 시세 :

자립 구현에는 구현 정의 된 헤더 집합이 있습니다. 이 집합에는 적어도 다음 표에 나와있는 것처럼 다음 헤더가 포함됩니다.

18.1 Types <cstddef>   
18.2 Implementation properties <limits>   
18.3 Start and termination <cstdlib> 
18.4 Dynamic memory management <new> 
18.5 Type identification <typeinfo> 
18.6 Exception handling <exception> 
18.7 Other runtime support <cstdarg>

Answer #7

어쩌면 .data 섹션을 컴파일하고 코드로 채울 수 있습니까?


Answer #8

이것이 오래된 질문이라는 것을 알았지 만, 나는 이것을 발견하고 나눌 필요가있었습니다. 아마도 모든 링커에서 작동하지는 않을 것이지만 적어도 다음 을 수행하여 주 기능 이 있다고 생각하도록 ld (2.24.51.20140918 버전을 실행 중입니다)를 속일 수 있습니다.

int main[] {};

심지어는

int main;

그런 다음 위의 트릭 중 하나를 적용하여 프로그램에서 생성자를 사용하여 코드를 실행할 수있게합니다.

struct Main
{
    Main()
    {
        cout << "Hello World!\n";
        exit(0);
    }
} main_;

exit(0) 은 배열이 "호출"되는 것을 방지합니다. 좋은 재미 :-)


Answer #9

주요 기능이없는 샘플 프로그램.

/* 
    7050925.c 
    $ gcc -o 7050925 7050925.c
*/

#include <stdio.h>
#define decode(s,t,u,m,p,e,d) m##s##u##t
#define begin decode(a,n,i,m,a,t,e)

int begin()
{
        printf("How mainless!\n");
}

보낸 사람 : http://learnhacking.in/c-program-without-main-function/


Answer #10

특정 언어 표준을 무시하면 대부분의 연결 로더는 이진 코드가로드 될 때 실행해야하는 함수 이름 (진입 점)을 선언하는 몇 가지 방법을 메모리에로드합니다.

예전의 C 언어의 경우 default는 ct 표준 함수 (예 : 메모리 힙 준비, 정적 변수 초기화)에 필요한 여러 가지 세대주 작업을 수행하는 crt (c runtime?)에 정의 된 'start'또는 '_start' 영역, argc / argv에 대한 명령 행 구문 분석 등

아마도 가정용 물건 (예 : malloc (), free (), printf (), 모든 클래스 정의에 사용자 정의 생성자가있는 표준 함수를 사용하지 않도록 충분히 신경 쓰면 엔트리 포인트 함수를 무시할 수 있습니다 ...) 표준 c 런타임이 아닌 o / s가 제공하는 기능을 사용하는 경우 제한적이지만 불가능하지는 않습니다.

예를 들어, 디스크립터 1에 write () 함수를 사용하여 간단한 helloworld를 만들 수 있습니다.


Answer #11

표준 C ++에서는 main 함수가 필요하므로 표준 C ++에서는 문제가되지 않습니다.

표준 C ++ 외부에서는 예를 들어 Windows 특정 프로그램을 작성하고 Microsoft의 사용자 정의 시작 기능 (wMain, winMain, wWinmain) 중 하나를 사용할 수 있습니다. Windows에서는 DLL로 프로그램을 작성하고 rundll32를 사용하여 실행할 수도 있습니다.

그 외에도 작은 런타임 라이브러리를 만들 수 있습니다. 한때 그것은 일반적인 스포츠였습니다.

마지막으로, 표준의 ODR 규칙에 따라 main 이 "사용되지"않았으므로 모든 프로그램이 자격을 얻도록 영리하고 반항 할 수 있습니다. 바하마! 면접관이 유머 감각이 뛰어나지 않는 한 (그리고 그들이 가진 질문을하지 않았을지라도) 좋은 대답이라고 생각하지 않을 것입니다.


Answer #12

함수 main은 프로그램이 실행을 시작할 주소의 기본 레이블입니다. 그래서 기술적으로는 가능하지만 환경에서 실행을 시작할 함수의 이름을 설정해야합니다.


Answer #13

main 은 엔트리 포인트, 코드가 실행되기 시작할 지점을 의미합니다. main 은 실행하는 첫 번째 기능은 아니지만. main 보다 먼저 실행되고 코드를 실행하기위한 환경을 준비하는 코드가 더 있습니다. 이 코드는 main 을 호출합니다. 시작 파일 crt0.c 의 코드를 다시 컴파일하고 main 함수의 이름을 변경하여 main 함수의 이름을 변경할 수 있습니다. 또는 다음을 수행 할 수 있습니다.

#include <stdio.h>

extern void _exit (register int code);

_start()
{
  int retval;
  retval = my_main ();
  _exit(retval);
}

int my_main(void)
{
  printf("Hello\n");
  return 0;
}

코드를 다음과 같이 컴파일하십시오.

gcc -o no_main no_main.c -nostartfiles

-nostartfiles 파일에는 기본 시작 파일이 포함되지 않습니다. _start 를 사용하여 기본 항목 파일을 가리 킵니다.

main 은 사용자 코드에 대한 사전 정의 된 엔트리 포인트입니다. 따라서 무엇이든 이름을 지정할 수는 있지만 하루가 끝나면 진입 점이 필요합니다. C / C ++ 및 다른 언어에서 다른 언어를 만들거나 이러한 언어 컴파일러의 소스를 해킹하면 main 이름이 변경 될 수 있지만 표준을 위반하므로 고통을 가져옵니다.

그러나 엔트리 함수 이름을 조작하는 것은 커널 코드, 커널에서 실행되는 첫 번째 함수 또는 임베디드 시스템 용으로 작성된 코드에 유용합니다.





main