parameter c++ c variadic-functions

parameter - c++ variadic templates



¿Para qué va_end exactamente? ¿Siempre es necesario llamarlo? (3)

En Linux x86-64, solo se puede realizar un va_list en una variable de va_list . Para hacer más recorridos, primero debe copiarse usando va_copy . man va_copy explica los detalles:

va_copy ()

Una implementación obvia tendría una lista_var como un puntero al marco de pila de la función variadic. En tal configuración (de lejos la más común) no parece haber nada en contra de una tarea

va_list aq = ap;

Desafortunadamente, también hay sistemas que lo hacen una serie de punteros (de longitud 1), y allí se necesita

va_list aq; *aq = *ap;

Finalmente, en sistemas donde los argumentos se pasan en registros, puede ser necesario que va_start () asigne memoria, almacene los argumentos allí, y también una indicación de qué argumento es siguiente, de modo que va_arg () pueda recorrer la lista. Ahora va_end () puede liberar la memoria asignada nuevamente. Para adaptarse a esta situación, C99 agrega una macro va_copy (), de modo que la asignación anterior se puede reemplazar por

va_list aq; va_copy(aq, ap); ... va_end(aq);

Cada invocación de va_copy () debe coincidir con una invocación correspondiente de va_end () en la misma función. Algunos sistemas que no proporcionan va_copy () tienen __va_copy en su lugar, ya que ese era el nombre utilizado en el borrador de la propuesta.

va_end - Macro para reiniciar arg_ptr .

Después de acceder a una lista de argumentos variables, el puntero arg_ptr generalmente se restablece con va_end() . Entiendo que es necesario si desea volver a iterar la lista, pero ¿es realmente necesario si no va a hacerlo? ¿Es solo una buena práctica, como la regla "siempre tener un default: en el switch "?


En la implementación común de "parámetros pasados ​​en la pila", creo que va_end () generalmente no es nada / vacío / nulo. Sin embargo, en plataformas que tienen esquemas menos tradicionales, se hace necesario. Es una "buena práctica" incluirlo para permanecer neutral en la plataforma.


va_end se usa para hacer la limpieza. No quieres destrozar la pila, ¿verdad?

Desde el man va_start :

va_end ()

Cada invocación de va_start () debe coincidir con una invocación correspondiente de va_end () en la misma función. Después de la llamada va_end (ap), la variable ap no está definida. Se pueden realizar múltiples recorridos de la lista, cada uno entre corchetes con va_start () y va_end (). va_end () puede ser una macro o una función.

Tenga en cuenta la presencia de la palabra debe .

La pila podría corromperse porque no sabes lo que va_start() está haciendo . Las macros va_* están destinadas a ser tratadas como cuadros negros. Cada compilador en cada plataforma puede hacer lo que quiera allí. Puede no hacer nada, o puede hacer mucho.

Algunos ABI pasan las primeras args en los registros, y el resto en la pila. Un va_arg() puede ser más complicado. Puede buscar cómo una implementación determinada hace varargs, lo que puede ser interesante, pero al escribir un código portátil debe tratarlos como operaciones opacas.