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 reiniciararg_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.