POSIX 시스템에서 argc가 0이 될 수 있습니까?
기본 프로그램에 대한 표준 정의가 주어지면 :
int main(int argc, char *argv[]) {
...
}
argcPOSIX 시스템 에서 어떤 상황에서 0 이 될 수 있습니까?
예, 가능합니다. 다음과 같이 프로그램을 호출하는 경우 :
execl("./myprog", NULL, (char *)NULL);
또는 또는 :
char *args[] = { NULL };
execv("./myprog", args);
그러면 "myprog"에서 argc0이됩니다.
이 표준 은 또한 argc호스팅 된 환경에서 프로그램 시작과 관련하여 섹션 5.1.2.2.1에 명시된대로 0 을 허용 합니다.
1 프로그램 시작시 호출되는 함수의 이름은
main. 구현은이 함수에 대한 프로토 타입을 선언하지 않습니다. 반환 유형int과 매개 변수없이 정의되어야합니다 .int main(void) { /* ... */ }또는 두 개의 매개 변수를 사용합니다 (여기에서
argc및 로 지칭됩니다.argv이름이 선언 된 함수에 로컬이기 때문에 모든 이름을 사용할 수 있음).int main(int argc, char *argv[]) { /* ... */ }또는 동등한 것; 또는 다른 구현 정의 방식으로.
2 선언 된 경우
main함수에 대한 매개 변수 는 다음 제약 조건을 따라야합니다.
- 의 값은
argc음수가 아니어야합니다.argv[argc]널 포인터 여야합니다....
이는 argc0이면 argv[0]NULL이 보장 된다는 것을 의미 합니다. 지정자에 printf대한 인수로 사용될 때 NULL 포인터를 처리하는 방법 은 %s표준에 나와 있지 않습니다. 이 경우 많은 구현에서 "(null)"을 출력하지만 보장되지는 않습니다.
다른 답변에 추가하려면 C (POSIX 여부)에는 main ()이 프로그램 내에서 함수로 호출되는 것을 방지하는 것이 없습니다.
int main(int argc, int argv[]) {
if (argc == 0) printf("Hey!\n");
else main(0,NULL);
return 0;
}
예, 0이 될 수 있습니다 argv[0] == NULL.
argv[0]프로그램의 이름 인 규칙입니다 . 당신은 할 수 있습니다 argc == 0당신과 같은 바이너리를 직접 실행하는 경우 가 execve 가족 및 인수를 포기하지 않습니다. 프로그램 이름에 가깝지 않은 문자열을 지정할 수도 있습니다. 그렇기 때문에 argv[0]프로그램 이름을 가져 오는 데 사용 하는 것이 완전히 신뢰할 수있는 것은 아닙니다.
일반적으로 명령 줄을 입력하는 셸은 항상 프로그램 이름을 첫 번째 인수로 추가하지만 이는 규칙입니다. 경우 argv[0]사용 == "--help"와 getopt는을 구문 분석 옵션 때문에 당신은 그것을 감지하지 않습니다 optind1로 초기화되지만 설정할 수 있습니다 optind0, 사용을 getopt표시하고 "도움말"긴 옵션을 선택합니다.
긴 이야기 짧게 : 그것은 완벽하게 가능합니다 argc == 0( argv[0]그 자체로는 특별하지 않습니다). 런처가 전혀 주장하지 않을 때 발생합니다.
초기 제안에서는 main ()에 전달 된 argc의 값이 "하나 이상"이어야했습니다. 이것은 ISO C 표준 초안의 동일한 요구 사항에 의해 주도되었습니다. 실제로 exec 함수의 호출자에게 인수가 제공되지 않은 경우 히스토리 구현은 0 값을 전달했습니다. 이 요구 사항은 ISO C 표준에서 제거되었으며 이후 POSIX.1-2017의이 볼륨에서도 제거되었습니다. 단어, 특히 단어의 사용은 Strictly Conforming POSIX 응용 프로그램이 exec 함수에 최소한 하나의 인수를 전달하도록 요구하므로 해당 응용 프로그램에서 호출 할 때 argc가 하나 이상임을 보장합니다. 실제로 많은 기존 응용 프로그램이 argc 값을 먼저 확인하지 않고 argv [0]을 참조하기 때문에 이것은 좋은 방법입니다.
Strictly Conforming POSIX 응용 프로그램에 대한 요구 사항은 또한 첫 번째 인수로 전달 된 값이 시작되는 프로세스와 관련된 파일 이름 문자열임을 명시합니다. 일부 기존 응용 프로그램은 경우에 따라 파일 이름 문자열이 아닌 경로 이름을 전달하지만 argv [0]의 일반적인 사용이 진단 인쇄에 사용되기 때문에 파일 이름 문자열이 더 일반적으로 유용합니다. 어떤 경우에는 전달 된 파일 이름이 파일의 실제 파일 이름이 아닙니다. 예를 들어, 로그인 유틸리티의 많은 구현은 실제 파일 이름에 ( '-') 접두사를 붙이는 규칙을 사용합니다. 이것은 호출되는 명령 인터프리터에게 "로그인 쉘"임을 나타냅니다.
또한 test 및 [유틸리티는 모든 구현에서 결정적 동작을 갖기 위해 argv [0] 인수에 대한 특정 문자열이 필요합니다.
POSIX 시스템에서 argc가 0이 될 수 있습니까?
예,하지만 POSIX를 엄격하게 준수하지는 않습니다.
당신이 어떤 실행 파일을 실행할 때마다 같은 ./a.out그것은 그게 하나 개의 인수를해야합니다 program name. 그러나 Linux에서 와 argc같이 프로그램을 실행하는 것은 .zeroexecvempty argument list
예를 들어
int main() {
char *buf[] = { NULL };
execv("./exe", buf); /* exe is binary which it run with 0 argument */
return 0;
}
요약 : 예, argv[0]NULL이 될 수 있지만 내가 아는 좋은 / 정상적인 이유가 아닙니다. 그러나 argv[0]NULL 인지 신경 쓰지 않는 이유가 있고, 만약 그렇다면 프로세스가 충돌하도록 특별히 허용 해야하는 이유 가 있습니다.
예, argv[0]인수없이 실행 된 경우에만 POSIX 시스템에서 NULL이 될 수 있습니다.
더 흥미로운 실질적인 질문은 프로그램이 관심을 가져야한다는 것 입니다.
The answer to that is "No, your program can assume argv[0] is not NULL", because some system utilities (command-line utilities) either do not work or work in a non-deterministic fashion, when argv[0] == NULL, but more importantly, there is no good reason (other than stupidity or nefarious purposes) why any process would do that. (I'm not sure if the standard usage of getopt() also fails then — but I would not expect it to work.)
A lot of code, and indeed most examples and utilities I write, begin with the equivalent of
int main(int argc, char *argv[])
{
if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
printf("Usage: %s [ -h | --help ]\n", argv[0]);
/* ... print usage ... */
return EXIT_SUCCESS;
}
and this is reasonable and acceptable, because there is no good reason for a process to exec another process without providing at least the command path being executed, i.e. execlp(cmd, cmd, NULL) rather than execlp(cmd, NULL).
(However, I can think of a few nefarious reasons, like exploiting timing race windows related to pipe or socket commands: an evil process sends an evil request via an established Unix domain socket, and then immediately replaces itself with an authorized victim command (run without any arguments, to ensure minimum start-up time), so that when the service getting the request checks the peer credentials, it sees the victim command, instead of the original evil process. It is, in my opinion, best for such victim commands to crash hard and fast (SIGSEGV, by dereferencing a NULL pointer), rather than try and behave "nicely", giving the evil process a larger time window.)
In other words, while it is possible for a process to replace itself with another but without any arguments causing argc to be zero, such behaviour is unreasonable, in the strict sense that there is no known non-nefarious reason to do so.
Because of this, and the fact that I love making life hard for nefarious and uncaring programmers and their programs, I personally will never add the trivial check, similar to
static int usage(const char *argv0)
{
/* Print usage using argv0 as if it was argv[0] */
return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
if (argc < 1)
return usage("(this)");
if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
return usage(argv[0]);
/* argv[0] and argv[1] are non-NULL, argc >= 2 */
except if requested by someone with a particular existing use case in mind. And even then I'd be a bit suspicious, wanting to verify the use case myself first.
참고URL : https://stackoverflow.com/questions/49817316/can-argc-be-zero-on-a-posix-system
'Program Club' 카테고리의 다른 글
| C #의 위도 / 경도 값에 대한 이중 또는 소수 (0) | 2020.10.23 |
|---|---|
| AndroidManifest xml 파일에서 android : supportsRtl =“true”사용은 무엇입니까? (0) | 2020.10.23 |
| 레일에서 파괴시 '검증'하는 방법 (0) | 2020.10.23 |
| 리팩토링이란 무엇이며 코드 만 수정하는 것은 무엇입니까? (0) | 2020.10.23 |
| Android에서 getSharedPreferences를 사용하는 방법 (0) | 2020.10.23 |