2009-02-25 2 views
46

va_end - 매크로를 재설정 arg_ptr.va_end는 정확히 무엇입니까? 항상 전화해야합니까?

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

+1

정말 좋은 질문입니다. 나는 누군가가 va_end가 no-op가 아닌 아키텍쳐를 기술함으로써 그것을 대답하기를 희망한다. – erikkallen

+1

참고 : MSVS2008 - #define _crt_va_end (ap = (va_list) 0) – Yarik

+0

@erikkallen : "va_end를 정의하십시오"에 대한 Google 검색을 수행하면 기본적으로 no- op. – PlasmaHH

답변

40

va_end은 정리 작업에 사용됩니다. 스택을 없애고 싶지 않니? man va_start 가입일

:

va_end의()

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

이어야합니다.

va_start()이 수행중인 내용이 인 경우 스택이 손상 될 수 있습니다. va_* 매크로는 검은 색 상자로 처리됩니다. 모든 플랫폼의 모든 컴파일러는 원하는 모든 것을 수행 할 수 있습니다. 그것은 아무 것도 할 수 없거나 많이 할 수 있습니다.

일부 ABI는 처음 몇 개의 args를 레지스터에 전달하고 나머지는 스택에 전달합니다. va_arg() 더 복잡 할 수 있습니다. 당신은 주어진 구현이 어떻게 가변적인지를 조사 할 수있다. 흥미로울 수도 있지만, 이식 가능한 코드를 작성하는 경우에는 불투명 한 조작으로 처리해야한다.

+0

포인터가 '전역'이라는 의미이며 포인터를 다시 설정하지 않고 함수를 두 번째 호출하면 스택이 손상됩니다. – Yarik

+3

* va_start()가 무엇을하는지 모르기 때문에 손상 될 수 있습니다. * 아무 것도 할 수 없습니다. 그리고 청소해야합니다. 따라서 va_start()를 호출하면 va_end()와 일치해야합니다. – greyfade

+0

설명해 주셔서 감사합니다. – Yarik

10

일반적으로 "스택에 전달 된 매개 변수"구현에서 va_end()는 일반적으로/empty/null이 아닌 것으로 간주합니다. 그러나 전통적인 방식이 적은 플랫폼에서는 필요합니다. 그것은 플랫폼 중립을 유지하기 위해 포함시키는 "좋은 습관"입니다.

+0

모든 var_args를 반복하지 않은 경우 스택을 재설정 할 수 있습니다. – Spidey

11

Linux x86-64의 경우 va_list 변수를 통해 하나의 순회 만 수행 할 수 있습니다. 더 많은 트래버스를 수행하려면 먼저 va_copy을 사용하여 복사해야합니다. man va_copy은 세부 사항을 설명합니다

va_copy()

확실한 구현이의 va_list는 가변 인자 함수의 스택 프레임에 대한 포인터가 될 것입니다.이러한 설정에서 (지금까지 일반적인 대부분의 는) 거기 (길이 1) 포인터의 배열을 만드는 시스템도 있으며,이 사람은

이 필요

va_list aq = ap; 

불행하게도 과제에 대하여 아무것도가 보인다

va_list aq; 
    *aq = *ap; 

마지막 인수 레지스터에 전달 시스템에서는 (즉 va_arg를 그래서 또한 va_start를() 를, 메모리 할당이 인수를 저장하고 인수가 옆에있는 표시에 필요한 수있다) 수 있습니다 단계 목록을 통해. 이제 va_end()는 할당 된 메모리를 다시 해제 할 수 있습니다 . 이러한 상황을 수용하기 위해, C99)는 (va_end에의 대응에 호출 될 능 일치해야 함) 상기 할당

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

va_copy 각 호출 (의해 대체 될 수있는 매크로 va_copy()이므로 추가 같은 기능으로 va_copy()를 제공하지 않는 일부 시스템은 초안 제안서에 사용 된 이름이므로 __va_copy를 대신 사용합니다.

+2

이것을 클리어링하려면; Linux x86-64에는 특별한 것이 없습니다. 'va_list' 변수 만 사용 가능할 때리스트를 두 번 반복하려면'va_copy'가 필요합니다. (예 : 인수로'va_list'를 취하는 함수 내부). 언제든지'va_start'와'va_end'를 원하는만큼 호출 할 수 있습니다. –

+0

@MattMcNabb x86-64에서'va_list'는 순회 상태를 유지합니다. x86에서는 그렇지 않습니다. –

+0

@downvoter 무엇이 잘못 되었나요? –

관련 문제