programing

C / C ++ 주 함수의 매개 변수는 어디에 있습니까?

nasanasas 2020. 12. 12. 11:06
반응형

C / C ++ 주 함수의 매개 변수는 어디에 있습니까?


C / C ++에서 main 함수는 유형의 매개 변수를받습니다 char*.

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

argv의 배열이며 char*문자열을 가리 킵니다. 이 문자열은 어디에 있습니까? 힙, 스택 또는 다른 곳에 있습니까?


실제로 컴파일러 의존성과 운영 체제 의존성의 조합입니다. main()다른 모든 C 기능과 같은 기능, 두 개의 매개 변수 때문에 위치입니다 argcargv플랫폼에서 컴파일러의 표준 따릅니다. 예를 들어 x86을 대상으로하는 대부분의 C 컴파일러의 경우 반환 주소와 저장된 기본 포인터 바로 위의 스택에 있습니다 (스택이 아래쪽으로 커짐을 기억하십시오). x86_64의 매개 변수가 레지스터에 전달됩니다에, 그렇게 argc될 것입니다 %ediargv에있을 것입니다 %rsi. 컴파일러에 의해 생성 된 주 함수의 코드는 스택에 복사합니다. 이것은 레지스터를에서 함수 호출에 사용할 수 있도록하기위한 것입니다 main.

char*argv가 가리키는 s 블록 과 실제 문자 시퀀스는 어디에나있을 수 있습니다. 일부 운영 체제 정의 위치에서 시작되며 링커가 스택 또는 다른 위치에 생성하는 프리앰블 코드에 의해 복사 될 수 있습니다. exec()링커가 생성 한 코드 와 어셈블러 프리앰블을 확인해야합니다.


그것들은 컴파일러 마법이며 구현에 따라 다릅니다.


다음은 C 표준 ( n1256 )의 내용입니다.

5.1.2.2.1 프로그램 시작
...
2 선언 된 경우 기능에 대한 매개 변수 는 다음 제약 조건을 준수해야합니다.

  • argc 의 값은 음수 아니 어야합니다.

  • argv [argc] 는 널 포인터 여야합니다.

  • argc 의 값 이 0보다 크면 argv [0] 부터 argv [argc-1] 까지 배열 멤버 는 프로그램 시작 전에 호스트 환경에 의해 구현 정의 값이 제공되는 문자열에 대한 포인터를 포함해야합니다. 그 목적은 호스팅 된 환경의 다른 곳에서 프로그램을 시작하기 전에 결정된 정보를 프로그램에 제공하는 것입니다. 호스트 환경이 대문자와 소문자가 모두 포함 된 문자열을 제공 할 수없는 경우 구현시 문자열이 소문자로 수신되는지 확인해야합니다.

  • argc 의 값 이 0보다 크면 argv [0]이 가리키는 문자열 프로그램 이름을 나타냅니다 . 호스트 환경에서 프로그램 이름을 사용할 수없는 경우 argv [0] [0] 은 널 문자입니다. argc 의 값 이 1보다 크면 argv [1] 에서 argv [argc-1] 까지 가리키는 문자열 프로그램 매개 변수를 나타냅니다 .

  • 매개 변수 argcargvargv 배열이 가리키는 문자열은 프로그램에 의해 수정 가능해야하며 프로그램 시작과 프로그램 종료 사이에 마지막으로 저장된 값을 유지해야합니다.

마지막 글 머리 기호는 문자열 값이 저장되는 가장 흥미로운 wrt입니다. 그것은 힙 또는 스택을 지정하지 않지만, 문자열이 쓸 수 할 것을 요구하고 있습니다 배치 정적 정도가 않습니다 일부 문자열 내용이 위치 할 수있는 위치에 대한 제한을. 다른 사람들이 말했듯이 정확한 세부 사항은 구현에 따라 다릅니다.


이 질문에 대한 대답은 컴파일러에 따라 다릅니다. 즉, C 표준에서 처리되지 않으므로 누구나 원하는대로 구현할 수 있습니다. 운영 체제에는 프로세스를 시작하고 완료하는 공통된 표준 방법이 없기 때문에 이는 정상입니다.

간단한 이유가 아닌 시나리오를 상상해 봅시다.

프로세스는 명령 줄에 기록 된 인수를 일부 메커니즘에 의해 수신합니다. argc는 컴파일러가 프로그램 프로세스 (런타임의 일부)에 대한 진입 점으로 넣은 부트 스트랩 함수에 의해 스택에 푸시되는 int입니다. 실제 값은 운영 체제에서 가져오고 힙의 메모리 블록에 기록 될 수 있습니다. 그런 다음 argv 벡터가 빌드되고 첫 번째 위치의 주소도 스택으로 푸시됩니다.

그런 다음 프로그래머가 제공해야하는 main () 함수가 호출되고 그 반환 값은 나중에 (거의 중간) 사용을 위해 저장됩니다. 힙의 구조가 해제되고 main에 대해 얻은 종료 코드가 운영 체제로 내보내집니다. 프로세스가 완료됩니다.


이 매개 변수는 다른 함수의 매개 변수와 다르지 않습니다. 아키텍처의 호출 시퀀스에 스택을 통과하는 매개 변수가 필요한 경우 스택에 있습니다. 마찬가지로 x86-64에서 일부 매개 변수가 레지스터에 들어가면 이것도 레지스터에 들어갑니다.


여기에 다른 많은 답변이 지적했듯이 컴파일러 구현이 main에 인수를 전달하는 데 사용하는 정확한 메커니즘은 표준에 의해 지정되지 않습니다 (컴파일러가 함수에 인수를 전달하는 데 사용하는 메커니즘). 엄밀히 말하면 컴파일러는 값이 구현에 의해 정의되기 때문에 해당 매개 변수에 유용한 어떤 것도 전달할 필요가 없습니다. 그러나 이들 중 어느 것도 특히 유용한 답변이 아닙니다.

The typical C (or C++) program is compiled for what's known as a 'hosted' execution environment (using function main() as the starting point of your program is one of the requirements for a hosted environment). The key thing to know is that the compiler arranges things so that when the executable is launched by the operating system, the compiler's runtime gets control initially - not the main() function. The runtime's initialization code performs whatever initialization is necessary, including allocating memory for the arguments to main(), then it transfers control to main().

The memory for the arguments to main() could come from the heap, could be allocated on the stack (possibly using techniques that aren't available to standard C code), or could use statically allocated memory, though that's a less likely option just because it's less flexible. The standard does require that the memory used for the strings pointed to by argv are modifiable and that modifications made to those string persist throughout the program's lifetime.

Just be aware that before execution reaches main(), quite a bit of code has already been run that's setting up the environment for your program to run in.


The argument list is part of the process environment, similar to (but distinct from) environment variables.


Usually it is unknown where they are.

#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
  char **foo;
  char *bar[] = {"foo", "bar"};

  (void)argv; /* avoid unused argv warning */

  foo = malloc(sizeof *foo);
  foo[0] = malloc(42);
  strcpy(foo[0], "forty two");

  /* where is foo located? stack? heap? somewhere else? */
  if (argc != 42) main(42, foo); else return 0;

  /* where is bar located? stack? heap? somewhere else? */
  if (argc != 43) main(43, bar); else return 0;
  /* except for the fact that bar elements
  ** point to unmodifiable strings
  ** this call to main is perfectably reasonable */

  return 0;
  /* please ignore memory leaks, thank you */
}

As pmg mentions, when main is called recursively, it's up to the caller where the arguments point to. Basically the answer is the same on the original invocation of main, except that the "caller" is the C implementation/OS.

On UNIX-y systems, the strings that argv points to, the argv pointers themselves, and the process's initial environment variables are almost always stored at the very top of the stack.


While you are able to access to the actual parameters, I think their actual location does not matter at all.

참고URL : https://stackoverflow.com/questions/4196201/where-are-c-c-main-functions-parameters

반응형