tipo que estándar caracteristicas aplicación c posix language-lawyer main

c - estándar - que tipo de kernel es linux



¿Puede argc ser cero en un sistema POSIX? (6)

Las primeras propuestas requerían que el valor de argc pasado a main () fuera "uno o más". Esto fue impulsado por el mismo requisito en los borradores del estándar ISO C. De hecho, las implementaciones históricas han pasado un valor de cero cuando no se proporcionan argumentos al llamador de las funciones ejecutivas. Este requisito se eliminó del estándar ISO C y posteriormente también se eliminó de este volumen de POSIX.1-2017. La redacción, en particular el uso de la palabra debería, requiere que una aplicación POSIX estrictamente conforme pase al menos un argumento a la función ejecutiva, garantizando así que argc sea uno o más cuando se invoque por dicha aplicación. De hecho, esta es una buena práctica, ya que muchas aplicaciones existentes hacen referencia a argv [0] sin verificar primero el valor de argc.

El requisito de una aplicación POSIX estrictamente conforme también establece que el valor pasado como primer argumento sea una cadena de nombre de archivo asociada con el proceso que se está iniciando. Aunque algunas aplicaciones existentes pasan una ruta de acceso en lugar de una cadena de nombre de archivo en algunas circunstancias, una cadena de nombre de archivo es más generalmente útil, ya que el uso común de argv [0] es en la impresión de diagnósticos. En algunos casos, el nombre de archivo pasado no es el nombre de archivo real del archivo; por ejemplo, muchas implementaciones de la utilidad de inicio de sesión utilizan una convención de prefijar un (''-'') al nombre de archivo real, lo que indica al intérprete de comandos que se invoca que es un "shell de inicio de sesión".

Además, tenga en cuenta que la prueba y [las utilidades requieren cadenas específicas para que el argumento argv [0] tenga un comportamiento determinista en todas las implementaciones.

Source

¿Puede argc ser cero en un sistema POSIX?

Sí, pero no sería estrictamente conforme a POSIX.

Dada la definición estándar para el programa principal:

int main(int argc, char *argv[]) { ... }

¿En qué circunstancias puede argc ser cero en un sistema POSIX?


Para agregar a las otras respuestas, no hay nada en C (POSIX o no) que impida que main () se llame como una función dentro del programa.

int main(int argc, int argv[]) { if (argc == 0) printf("Hey!/n"); else main(0,NULL); return 0; }


Sí, es posible. Si llama a su programa de la siguiente manera:

execl("./myprog", NULL, (char *)NULL);

O alternativamente:

char *args[] = { NULL }; execv("./myprog", args);

Luego, en "myprog", argc será 0.

El estándar también permite específicamente un 0 argc como se señala en la sección 5.1.2.2.1 con respecto al inicio del programa en un entorno alojado:

1 La función llamada al inicio del programa se denomina main . La implementación no declara ningún prototipo para esta función. Se definirá con un tipo de retorno de int y sin parámetros:

int main(void) { /* ... */ }

o con dos parámetros (referidos aquí como argc y argv , aunque se pueden usar nombres, ya que son locales para la función en la que se declaran):

int main(int argc, char *argv[]) { /* ... */ }

o equivalente; o de alguna otra manera definida por la implementación.

2 Si se declaran, los parámetros de la función main obedecerán las siguientes restricciones:

  • El valor de argc no será negativo.
  • argv[argc] será un puntero nulo.

...

Tenga en cuenta también que esto significa que si argc es 0, entonces se garantiza que argv[0] será NULL. Sin printf forma en que printf trata un puntero NULL cuando se usa como argumento para un especificador %s no se detalla en el estándar. Muchas implementaciones generarán "(nulo)" en este caso, pero no creo que esté garantizado.


Sí, puede ser cero, lo que significa que argv[0] == NULL .

Es una convención que argv[0] es el nombre del programa. Puede tener argc == 0 si inicia el binario, como con execve family y no da ningún argumento. Incluso puede dar una cadena que no esté cerca del nombre del programa. Es por eso que usar argv[0] para obtener el nombre del programa no es del todo confiable.

Por lo general, el shell donde escribe su línea de comandos siempre agrega el nombre del programa como primer argumento, pero nuevamente, es una convención. Si argv[0] == "--help" y usa la opción getopt para analizar, no lo detectará porque optind se inicializa en 1, pero puede establecer optind en 0, use getopt y la opción larga "help" mostrará arriba.

larga historia corta: es perfectamente posible tener argc == 0 ( argv[0] no es realmente especial por sí mismo). Sucede cuando el lanzador no da argumentos en absoluto.


TL; DR: Sí, argv[0] puede ser NULL, pero no por ninguna razón buena / sensata que conozca. Sin embargo, hay razones para no preocuparse si argv[0] es NULL y para permitir específicamente que el proceso se bloquee si lo es.

Sí, argv[0] puede ser NULL en un sistema POSIX, si y solo si se ejecutó sin ningún argumento.

La pregunta práctica más interesante es si su programa debe preocuparse .

La respuesta a eso es "No, su programa puede asumir que argv[0] no es NULL" , porque algunas utilidades del sistema (utilidades de línea de comandos) no funcionan o funcionan de manera no determinista, cuando argv[0] == NULL , pero lo más importante, no hay una buena razón (aparte de la estupidez o los propósitos nefastos) por qué cualquier proceso haría eso. (No estoy seguro si el uso estándar de getopt() también falla entonces, pero no esperaría que funcione).

Una gran cantidad de código, y de hecho la mayoría de los ejemplos y utilidades que escribo, comienzan con el equivalente de

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; }

y esto es razonable y aceptable, porque no hay una buena razón para que un proceso ejecute otro proceso sin proporcionar al menos la ruta de comando que se está ejecutando, es decir, execlp(cmd, cmd, NULL) lugar de execlp(cmd, NULL) .

(Sin embargo, puedo pensar en algunas razones nefastas, como explotar ventanas de carrera de tiempo relacionadas con comandos de tubería o socket: un proceso maligno envía una solicitud maliciosa a través de un socket de dominio Unix establecido, y luego se reemplaza inmediatamente con un comando de víctima autorizado (ejecutar sin ningún argumento, para garantizar un tiempo de inicio mínimo), de modo que cuando el servicio que recibe la solicitud verifique las credenciales de los pares, vea el comando de la víctima, en lugar del proceso maligno original. En mi opinión, es lo mejor para esa víctima comandos para bloquearse duro y rápido ( SIGSEGV , al desreferenciar un puntero NULL), en lugar de intentar comportarse "bien", dando al proceso maligno una ventana de tiempo más grande).

En otras palabras, si bien es posible que un proceso se reemplace por otro, pero sin ningún argumento que argc que argc sea ​​cero, dicho comportamiento no es razonable, en el sentido estricto de que no hay una razón no nefasta conocida para hacerlo.

Debido a esto, y al hecho de que me encanta hacer la vida difícil para los programadores nefastos e indiferentes y sus programas, personalmente nunca agregaré el control trivial, similar a

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 */

excepto si lo solicita alguien con un caso de uso existente en particular en mente. E incluso entonces sospecharía un poco, queriendo verificar el caso de uso primero.


cada vez que desee ejecutar cualquier ejecutable como ./a.out tendrá un argumento que es el program name . Pero es posible ejecutar un programa con argc como zero en Linux, ejecutándolo desde otro programa que llama a execv con una empty argument list .

por ej.

int main() { char *buf[] = { NULL }; execv("./exe", buf); /* exe is binary which it run with 0 argument */ return 0; }