2015-02-02 3 views
0

.dtors의 함수와 atexit()이라는 함수의 차이점은 무엇입니까?C++에서 .dtors와 atexit()의 차이점

내가 알기로 ((destructor)) 속성으로 표시된 기능은 .dtors 세그먼트에 있으며 종료 후 호출됩니다. 마찬가지로 atexit(fctName)을 사용하여 추가 된 함수는 배열에 배치되고 일반 실행 종료 후에도 호출됩니다.

그렇다면 C++은 왜 두 가지 별개의 메커니즘을 제공합니까? 하나만 할 수있는 뚜렷한 것들이 있습니까? atexit()을 사용하여 동적으로 함수를 추가 할 수 있습니까?

.dtors의 함수 또는 atexit()의 함수가 추가 된 함수도 있습니다.

+0

C++은 .dtors 세그먼트를 제공하지 않습니다. 구현 세부 사항입니다. 'destructor' 속성은 표준에 의해서도 정의되어 있지 않습니다. 그것은 (C) 언어의 확장입니다. 'atexit'는 C 표준에 정의되어 있으므로 C에서 상속 받았기 때문에 C++에 있다고 말할 수 있습니다. – user2079303

답변

0

C++에는 .dtors이 없습니다. 구현에 따라 달라질 수 있습니다. 전역 객체의 소멸자를 추적하는 합리적인 메커니즘입니다. 내가 알기에 그것은 컴파일 시간 목록이다.

atexit 런타임에 처리기가 추가됩니다. 즉, 런타임에 필요할 때만 함수를 추가 할 수 있습니다.

질문 (더 자세한 내용)의 마지막 부분에 대한

, 정적 객체의 소멸자의 When is a function registered with atexit() called

+0

파괴 순서는 순서의 역함과 일치해야하므로 컴파일 시간 목록이 될 수 없습니다. 'atexit' 호출을 올바르게 삽입해야합니다. –

+0

@JamesKanze : 그게 왜 문제인지 정확히 알 수 없습니까? '.dtors'리스트는 컴파일 된 함수 포인터의 목록입니다.이 목록은 동적으로 일부'__atexit__internal'리스트에 상응하는'.ctors' 완료로 나타납니다. 인터리빙'atexit()'호출이 있다면, 그것들은'__atexit_internal'리스트에 추가 될 것입니다. 하지만 요점은 테이블 항목과'atexit()'인수를 병합하여 목록이 동적으로 작성된다는 것입니다. – MSalters

+0

내 답변에 대한 귀하의 의견에 대한 내 대답을보십시오. 기본적으로, 단순한 경우를 고려하고,'std :: atexit'를 호출하는 지역 통계와 이니셜 라이저를 무시하는 것처럼 보입니다. 표준에'atexit'로 등록 된 함수와 정적 객체의 소멸자가'atexit' 및 생성자에 대한 호출의 역순으로 순서가되어야한다는 사실이 필요합니다. –

-1

한 법적 구현이 생성자이 완료되면 atexit와 에게이를 등록하는 것입니다 참조하십시오. 표준은이 구현이 사용 된 것과 동일한 순서를 요구합니다. 가장 큰 차이점은 정적 객체 의 소멸자가 소멸자가 있다는 것입니다 : 개체가 가 완전히 구성되면 그들은 에게이를 등록하는 당신의 부분에 어떤 필요없이, 자동으로 호출됩니다. 개체에 액세스하려면 this 매개 변수가 있어야합니다.

는 편집 :

는 완벽하게 명확하게하려면 :

void __destructObj() 
{ 
    obj.~T(); 
} 

다음과 같은 초기화 코드 :

new (&obj) T; 
std::atexit(__destructObj); 
주어진

T obj;  // where obj has static lifetime... 

컴파일러는 함수를 생성하는 것

범위에 관계없이 obj; 동일한 기본 코드는 에 대해 로컬 정적 및 네임 스페이스 범위의 개체에서 작동합니다. ( 로컬 개체의 경우 컴파일러는 개체가 이미 초기화되었는지 여부를 나타 내기 위해 플래그를 생성하고 코드를 생성해야하며 스레드 안전을 보장하기 위해 조치를 취해야합니다.

실제로 컴파일러가 어떻게 할 수 있는지 알기는 어렵습니다. (코드를 인라인으로 생성하여 std::atexit을 수행 할 수도 있음), 주문 요구 사항이 입니다.

+0

전역 객체의 소멸자에 대해'this' 포인터를 어떻게 등록 하시겠습니까? 뒤에서는 인터리빙이 문서화 된 동작이므로 일부 일반적인 메커니즘이 있어야하지만 공용'atexit' API 만 다시 사용할 수는 없습니다. – MSalters

+0

@MSalters 컴파일러는 인수를 취하지 않는 함수를 생성하고이를 등록해야합니다. 너무 어렵지는 않습니다. 왜냐하면 그것은 객체의 주소를 알고 있기 때문입니다. 반면에, 표준에서의 순서 제약은 동적 등록을 요구합니다 :'T o1; bool b = (std :: atexit (f), true); T o2;', 표준은'~ T (o2); 에프(); ~ T (o1);'. (왜 다른 질문입니까? 실제로 그런 물건을 쓴 사람은 누구나 사격 당할 가치가 있습니다.) –

+0

조금 복잡해 보입니다 (도우미 함수의 오버 헤드가 상당히 클 수 있습니다).왜 누군가가 이것을 필요로하는지, 필자는 Andrei Alexandrescu의 적절한 정리 (Phoenix Singleton, IIRC, Modern C++ Design)에 대한 논쟁이 있었다고 생각합니다. – MSalters

1

linux man-pages atexit()는 exit (3) 또는 프로그램의 main()에서 반환을 통해 정상 프로세스 종료시 호출됩니다.

.ctors/.dtors는 정의 된 공유 라이브러리가로드/언로드 될 때 호출됩니다.

이러한 순서는 매우 분명합니다.

+0

공유 라이브러리와 관련하여 ... 표준에 관한 한 정의되지 않은 동작입니다. 그러나 C++ 표준은 소멸자와'atexit '로 등록 된 함수의 적절한 인터리빙을 필요로합니다. 과거에는 (나는 아직도 그런 일이 있는지 모르겠다.) g ++은 이런 점에서 몇 가지 문제점을 가지고 있었고 항상 준수하지는 않았다 :'__cxa_atexit1'을 보라. –

+0

공유 라이브러리가 소멸자의 코드와 같은 일을하는 atexit() 함수를 호출하면 동작이 달라 집니까? – Rafa

+0

[이 엔트리] (http://stackoverflow.com/questions/10702980/atexit-function)이 질문에 대한 대답 인 것 같습니다. glibc 구현 외부에서 실행하면 정의되지 않은 동작이됩니다. – Tom

관련 문제