Pergunta

va_end -. Macro para repor arg_ptr

Depois de acessar uma lista de argumentos variável, o ponteiro arg_ptr geralmente é redefinir com va_end(). Eu entendo que é necessário se você quiser re-iterate a lista, mas é realmente necessário se você não está indo? É apenas boas práticas, como a regra de "ter sempre um default: em sua switch"?

Foi útil?

Solução

va_end é usado para fazer a limpeza. Você não quer esmagar a pilha, não é?

De man va_start:

va_end ()

Cada chamada de va_start () tem de ser compensada por uma correspondente invocação de va_end () na mesma função. Após a va_end chamada (ap) a ap variável é indefinido. Vários percursos da lista, cada enquadradas por va_start () e va_end () são possíveis. va_end () pode ser uma macro ou uma função.

Observe a presença da palavra deve .

A pilha pode ser corrompido porque você não sabe o que está fazendo va_start() . As macros va_* são feitos para serem tratadas como caixas pretas. Cada compilador em cada plataforma pode fazer o que quiser lá. Pode não fazer nada, ou pode fazer muita coisa.

Alguns ABIs passar os primeiros argumentos em registos, eo restante na pilha. A va_arg() pode haver mais complicado. Você pode olhar para cima como uma determinada aplicação não varargs, o que pode ser interessante, mas em escrever código portátil que você deve tratá-los como operações opacos.

Outras dicas

No Linux x86-64 apenas um percurso pode ser feito sobre uma variável va_list. Para fazer mais traversals tem que ser copiado usando va_copy primeiro. man va_copy explica os detalhes:

va_copy ()

Uma implementação óbvia teria um va_list ser um ponteiro para a quadro de pilha da função variádica. Em tal configuração um (de longe a mais comum) não parece nada contra uma atribuição

   va_list aq = ap;

Infelizmente, existem também sistemas que tornam uma matriz de ponteiros (Comprimento de 1), e existe uma necessidade

   va_list aq;
   *aq = *ap;

Finalmente, em sistemas onde os argumentos são passados ??nos registos, pode ser necessária para va_start () para alocar memória, armazenar os argumentos lá, e também uma indicação de que argumento é próximo, de modo que va_arg () lata percorrer a lista. Agora va_end () pode liberar a memória alocada novamente. Para acomodar esta situação, C99 adiciona um va_copy macro (), então que a atribuição acima pode ser substituído por

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

Cada invocação de va_copy () deve ser acompanhada por uma invoca- correspondente ção de va_end () na mesma função. Alguns sistemas que não fornecem va_copy () tem __va_copy em vez disso, uma vez que era o nome usado na projecto de proposta.

Nos "parâmetros passados ??na pilha" comuns implementação, acredito va_end () é geralmente nada / vazia / null. No entanto, em plataformas que possuem esquemas menos tradicionais, torna-se necessário. É uma "boa prática" para incluí-lo para permanecer plataforma neutra.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top