program story

va_end는 정확히 무엇입니까?

inputbox 2020. 12. 31. 08:15
반응형

va_end는 정확히 무엇입니까? 항상 전화해야합니까?


va_end-재설정 할 매크로 arg_ptr.

가변 인수 목록에 액세스 한 후 arg_ptr포인터는 일반적으로로 재설정됩니다 va_end(). 나는 당신이 목록을 반복하고 싶다면 그것이 필요하다는 것을 이해하지만, 당신이 그렇게하지 않을 경우 정말로 필요합니까? 규칙 "항상 default:당신의 switch" 와 같은 좋은 습관 입니까?


va_end정리하는 데 사용됩니다. 스택을 부수고 싶지 않습니까?

에서 man va_start:

va_end ()

va_start ()의 각 호출은 동일한 함수에서 va_end ()의 해당 호출과 일치해야합니다. va_end (ap) 호출 후 변수 ap는 정의되지 않습니다. va_start () 및 va_end ()로 각각 괄호로 묶인 목록의 여러 순회가 가능합니다. va_end ()는 매크로 또는 함수일 수 있습니다.

must 라는 단어의 존재에 유의하십시오 .

무엇 va_start()을하고 있는지 모르기 때문에 스택이 손상 될 수 있습니다. va_*매크로는 블랙 박스로 취급하기위한 것입니다. 모든 플랫폼의 모든 컴파일러는 원하는 것을 할 수 있습니다. 아무것도하지 않거나 많은 일을 할 수 있습니다.

일부 ABI는 레지스터의 처음 몇 개의 인수와 스택의 나머지 인수를 전달합니다. A va_arg()더 복잡 할 수 있습니다. 주어진 구현이 어떻게 varargs를 수행하는지 찾아 볼 수 있습니다. 이것은 흥미로울 수 있지만 이식 가능한 코드를 작성할 때는이를 불투명 한 작업으로 처리해야합니다.


Linux x86-64에서는 va_list변수에 대해 하나의 순회 만 수행 할 수 있습니다 . 더 많은 순회를 수행하려면 va_copy먼저 사용하여 복사해야합니다 . man va_copy세부 사항을 설명합니다 :

va_copy ()

명백한 구현은 va_list가 variadic 함수의 스택 프레임에 대한 포인터가 될 것입니다. 그러한 설정 (지금까지 가장 일반적인)에서는 과제에 반대하는 것이 없습니다.

   va_list aq = ap;

불행히도 포인터 배열 (길이 1)을 만드는 시스템도 있습니다.

   va_list aq;
   *aq = *ap;

마지막으로, 인수가 레지스터에 전달되는 시스템에서는 va_start ()가 메모리를 할당하고, 여기에 인수를 저장하고, 다음 인수를 표시하여 va_arg ()가 목록을 통과 할 수 있도록해야 할 수 있습니다. 이제 va_end ()는 할당 된 메모리를 다시 해제 할 수 있습니다. 이러한 상황을 수용하기 위해 C99는 va_copy () 매크로를 추가하여 위의 할당을 다음으로 대체 할 수 있습니다.

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

va_copy ()의 각 호출은 동일한 함수에서 va_end ()의 해당 호출과 일치해야합니다. va_copy ()를 제공하지 않는 일부 시스템에는 제안 초안에 사용 된 이름이므로 대신 __va_copy가 있습니다.


일반적인 "스택에 전달 된 매개 변수"구현에서, 나는 va_end ()가 보통 아무것도 / 비어 있거나 / 널이라고 생각합니다. 그러나 전통적인 방식이 덜한 플랫폼에서는 필요합니다. 플랫폼 중립을 유지하기 위해 포함하는 것이 "좋은 관행"입니다.

참조 URL : https://stackoverflow.com/questions/587128/what-exactly-is-va-end-for-is-it-always-necessary-to-call-it

반응형