2011-02-15 3 views
1

내 멀티 스레드 응용 프로그램 (C++, SunOS)은 공유 라이브러리와 동적으로 링크됩니다. 프로그램에 여러 개의 스레드가 있으며, 그 중 일부는 라이브러리에 있습니다. 이러한 스레드 중 하나는 종료()를 호출하고 공유 라이브러리에 다른 스레드에서 코어 덤프를 생성하는 결과 :죽어가는 다중 스레드 프로세스의 코어 덤프

(dbx) where 
    [1] 0x0(0xbeee0b30, 0x0, 0x0, 0x1c00, 0x1, 0xbeee0b50), at 0x0 
    [2] STLCollectionWrapper<std::vector<SM_Timer*,std::allocator<SM_Timer*> > >::empty(0xbeee0b30, 0x0, 0x0, 0x1c00, 0xbca12200, 0x0), at 0xbee04690 
    [3] GenPtrSortVec<SM_Timer,std::less<SM_Timer>,std::allocator<SM_Timer> >::isEmpty(0xbeee0b30, 0x0, 0x0, 0x0, 0x4fb0e0, 0xbd436b90), at 0xbee04424 
    [4] sm_tmr_process(0x341000, 0x8e400, 0xbeeba00f, 0x1c00, 0x1, 0xbeee0800), at 0xbee03968 
    [5] sm_nm_process_timeouts(0xbc67bf94, 0xbc67bf98, 0xbd4c3800, 0x0, 0xbca12200, 0xbee830f0), at 0xbee813dc 
    [6] TimerThreadObject::poll(0x0, 0xbc67c000, 0x0, 0x0, 0xbedf1530, 0x1), at 0xbedf15f4 
(dbx) thread 
current thread ($thread) is [email protected] 
(dbx) lwps 
    [email protected] LWP suspended in __SLIP.FINAL__A() 
    [email protected] LWP suspended in find_composition_start() 
o>[email protected] signal SIGSEGV in 0x0() 

스택은 6-4 LIBA 출신 프레임, libB에서 3-2 프레임. 프레임 1은 C++ 표준 라이브러리 (/usr/lib/libCstd.so.1?)에서 호출해야합니다. 보시다시피,이 호출은 실패했습니다.

프레임 4에서 코드는 GenPtrSortVec 유형의 전역 개체 isEmpty() 메서드를 호출했습니다. 이 객체는 sm_tmr_process() 메소드가 정의 된 동일한 모듈의 스택에 있습니다. 나중에 프레임 2에서 코드는 STL 벡터 객체의 empty() 메서드를 호출합니다. 이 벡터는 GenPtrSortVec 클래스의 필드입니다.

I가이 문제와 관련하여 다음과 같은 질문 : 첫 번째 프레임은 0x0 주소를 가지고 왜

  1. ?

  2. libCstd가 프로그램의 모든 스레드를 취소하기 전에 죽어가는 프로세스에서 언로드되었을 수 있습니까? libCstd는 동적 종속성으로 프로세스에 자동으로로드되었습니다.

그리고 그 과정에서 종료에 대한 자세한 두 가지 질문 :

  1. 가 자동으로 공유로드 된 라이브러리가 자동으로 모든 스레드를 취소하고 정적/전역 개체를 파괴하기 전에 언로드되었다고 할 수 있습니까?

  2. 모든 스레드를 취소하기 전에 전역 개체 또는 정적 개체가 파괴되었을 가능성이 있습니까?

+0

** libA.cpp ** : 'GenPtrSortVec < SM_Timer > timeoutList; void sm_tmr_process() { \t timeoutList.isEmpty(); }' ** libB.h ** : [링크] (http://pastebin.com/PdvmfiTs) – darkshine

답변

1

1에 대한 응답 : 아마도 NULL 함수 포인터를 호출했습니다. 직접적으로는 아니지만 간접적으로는 가능합니다. 객체의 vtable을 0으로 덮어 쓰고 가상 메소드를 호출 할 수 있습니까?

+0

단지 사소한 설명 : 나는 가정하더라도 VTABLE 자체가 보통 (읽기 전용 메모리에 상주한다 이것은 구현에 따라 다릅니다.) 덮어 쓸 수있는 것은 vtable에 대한 포인터입니다. – sstn

+0

vtable에 대한 포인터를 덮어 쓰면 NULL에 충돌하지 않습니다. vtable 포인터를 역 참조하는 것은 호출 사이트에서 중단되어야합니다. 맞습니까? –

+0

@ Jörgen 나는 그것이 달려 있다고 말하고 싶습니다. 잘못된 포인터를 역 참조하는 것은 정의되지 않은 동작이므로 나중에 모든 것이 가능합니다 ;-) - 0으로 덮어 쓰면 실제로 호출 사이트에서 충돌합니다. 만약 다른 것으로 덮어 쓰게된다면, vtable의 관련 pointe가 NULL을 가리키고 있음을 알게 될 것입니다. 적어도 저의 저녁은 제 이해입니다. – sstn

2

1.1 - 가능성이 널 포인터 호출 (요르겐 참조)

1.2 - 아니

2.1 - 아니

2.2 - 아마도

1.2/2.1 : 공유 라이브러리를로드 할 때 프로그램이 메모리에로드됩니다. 그러면 동적 링커가 모든 외부 참조를 스캔하여 수정합니다. 이것이 동적 연결 과정입니다. 이 작업은 실행 취소되지 않습니다. 즉,이 방법으로로드 된 라이브러리가 OS에서 언로드되지 않습니다. 프로그램이 종료되면 전체 프로세스 이미지가 삭제됩니다.

2.2 - 응용 프로그램에 따라 다릅니다. 전역/공유 객체의 초기화는 문제가 될 수 있습니다. 정적 초기화 실패를 참조하십시오. 파괴에도 똑같이 적용됩니다. 두 경우의 순서는 구현에 따라 결정됩니다.