2011-08-17 5 views
0

C++ 라이브러리를 호출하는 기존 .NET (C#, 3.5) 응용 프로그램에서 이상한 Boost (v1.38) 뮤텍스 교착 상태가 발생했습니다. 예외는 읽기 잠금을 얻은 시점에서 [제대로] 던져지고 그 예외는 관리되는 .NET 코드 (처리되는 곳)로 다시 처리되지 않게됩니다. 세터 방법을 사용하려고 시도 라이브러리 ++은 C에 대한 다음 호출이 indefinately 고유 잠금 aquisition에 달려 (아마도 읽기 잠금이 해제되지 않은) :예외를 던진 후 부스트 공유 뮤텍스가 해제되지 않았습니다.

ntdll.dll!NtWaitForSingleObject() + 0x15 bytes 
kernel32.dll!WaitForSingleObjectEx() + 0x43 bytes 
kernel32.dll!WaitForSingleObject() + 0x12 bytes 
OurCPPLib.dll!boost::shared_mutex::unlock_upgrade_and_lock() Line 478 + 0x11 bytes C++ 
OurCPPLib.dll!boost::unique_lock<boost::shared_mutex>::unique_lock<boost::shared_mutex>(boost::detail::thread_move_t<boost::upgrade_lock<boost::shared_mutex> > other) Line 788 C++ 
OurCPPLib.dll!boost::upgrade_to_unique_lock<boost::shared_mutex>::upgrade_to_unique_lock<boost::shared_mutex>(boost::upgrade_lock<boost::shared_mutex> & m_) Line 802 + 0x98 bytes C++ 
OurCPPLib.dll!OurClass::SetSomething(double something) Line 95 C++ 

을 클래스는 (가져 오기 및 설정 방법 독자의 수를 정의/작가)와 지금처럼 구현 : 또한,

throw std::invalid_argument("Unknown something"); 

: _anotherObject-> GetSomething (에 대한 호출이) 드문 조건에서 예외가 발생합니다

boost::shared_mutex _calcSharedMutex; 

RETURNCODE GetSomething(double& something) 
{ 
    boost::shared_lock<boost::shared_mutex> lock(_calcSharedMutex); 
    return _anotherObject->GetSomething(something); 
} 

RETURNCODE SetSomething(double something) 
{ 
    boost::upgrade_lock<boost::shared_mutex> lock(_calcSharedMutex); 
    boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock); 
    return _anotherObject->SetSomething(something); 
} 

_anotherObject-> GetSomething()에 대한 getter 내의 일부 호출은 C++ 라이브러리 자체에서 try/catch 내에서 수행되어 예외가 관리되는 코드로 돌아 가지 않도록하며이 교착 상태가 발생하지 않습니다. 처리되지 않은 예외가 부스트 뮤텍스 범위 잠금을 해제합니까?

사전 통찰력을 가진 사람에게 감사드립니다!

+0

이 코드는/clr로 컴파일되어 있습니까? 그렇다면 #pragma managed (push, off)를 앞에 두 었는가? –

+0

C++은/clr 스위치와 함께 컴파일되지 않습니다. – roken

+0

글쎄 그건 이상한 일이다. 실제로 문제를 보여주는 데모 프로그램 외에도/EHa로 C++ 코드를 컴파일하는 유일한 방법이 있습니다. * 그것이 효과가 있다는 것은 이해가되지 않지만. –

답변

0

네이티브 태어난 예외가 관리되는 코드에서 처리 될 때 스택이 해제되지 않도록하는 2.0 CLR의 버그가 있습니다. 4.0 CLR이 문제를 해결에

Microsoft Connect: /Ehsc & /Eha & stack unwinding

은 실행 실행 관리 전환.

참고로 기본 CLR 라이브러리는 2.0 CLR을 대상으로하는 관리되는 C# 라이브러리에서 호출되었습니다. 관리되는 어셈블리는 실행 파일 (4.0)의 버그없는 CLR에서 실행되므로 2.0 CLR을 계속 대상으로 지정할 수 있지만 2.0 호환 모드에서 실행됩니다.

2

처리되지 않은 예외가 발생할 때 스택이 unwound되는지 여부는 C++에서 지정되지 않습니다. 일부 구현은 그렇게합니다 (소멸자와 다른 모든 일이 발생해야 함). 그렇지 않은 경우도 있습니다. C++/CLI가 어떻게 처리하는지 정확히 모르겠지만 C++ 파트가 처리되지 않은 것으로 예외를 확인하면 스택을 풀지 않을 수 있으므로 소멸자를 호출하지 않고 뮤텍스를 릴리스 할 수 있습니다 .

그러나 이것은 단지 추측이다 (그래서, 단순히 잡기와 문제를 해결해야하는 C++ 코드에서 예외를 rethrowing 경우). 필자는 C++/CLI를 많이 사용하지 않았으며, 네이티브 코드와 관리 코드간에 예외가 어떻게 전파되는지 전혀 알지 못합니다.

관련 문제