2013-05-20 3 views
9

필자가 작성하지 않은 실행 파일에서 실행중인 쓴 DLL에서 오는 "첫 번째 예외 예외"메시지가 있습니다. 즉, DLL은 플러그인입니다. 이 예외가 처음으로 발생하면 공유 메모리 맵 파일 열기 시도가 실패합니다. 첫 번째 예외를 무시하고 그냥 실행하면 결국 응용 프로그램이 멈추거나 충돌합니다. 몇 시간 후boost :: interprocess managed_shared_memory가 관련된 무한 루프 및 힙 손상 문제를 디버그하거나 수정하려면 어떻게합니까?

First-chance exception at 0x76a7c41f in notmyexe.exe: Microsoft C++ exception: boost::interprocess::interprocess_exception at memory location 0x002bc644.. 

예상 예외 조건이 클리어 될 때까지 끝없이 반복되는 코드 블록에 의한 것으로 보인다. 분명히 밝혀지지 않으면 궁극적으로이 예외는 다른 저수준 예외 상황으로 바뀌거나 힙 손상으로 바뀝니다. 이 모든 것은 단지 Boost :: interprocess를 사용하여 공유 메모리 영역을 여는 데있다. 일을 복잡하게

우선 내 비주얼 C++ 2008 기반 프로젝트에 첫 번째 boost::interprocess::interprocess_exception 첫 번째 예외가 발생되지 않고는 비주얼 C++ 2008 컴파일러는 복잡한 향상을 찾을 수 없기 때문에 온 위치로 확인한다는 것입니다 문제의 템플릿 코드를 맛보기. 그러나 어셈블리 언어 뷰를 한 단계 씩 진행하면 코드가 폭발적으로 증가합니다.

segment = new managed_shared_memory( open_or_create 
             , MEMORY_AREA_NAME 
             , SHARED_AREA_SIZE);   

managed_shared_memory 클래스는 interprocess_fwd.hpp에서, 그리고 부스트 공유 메모리 API의 표준 일부입니다

모든이에 나쁜 이동하기 시작 내 자신의 코드의 최상위 라인입니다/헤더. 템플릿 기반이기 때문에 위의 내용은 링커 및 디버거가 서로 다른 길이로 잘린 약 2Kchars 길이의 C++ 부스트 템플릿 표현식으로 확장됩니다. Visual C++ 2008에는 더 이상의 소스 코드 디버깅 기능이 없습니다. 이러한 제한이 작용할 때 나타납니다. 로 작성된 소스 기능을 스택에 표시

KernelBase.dll!76a7c41f() 
    [Frames below may be incorrect and/or missing, no symbols loaded for KernelBase.dll]  
    KernelBase.dll!76a7c41f() 
> msvcr90d.dll!_malloc_dbg(unsigned int nSize=2290875461, int nBlockUse=264, const char * szFileName=0x01fcb983, int nLine=1962999808) Line 160 + 0x1b bytes C++ 
    8bfc4d89() 

실제 최종 사용자가 위의 덤프 없습니다 : 그것은 불면 때

예를 들어

는,이 호출 스택을 얻을.

어떻게 디버깅해야합니까? 둘째, Visual C++ 2008과 함께 boost-interprocess와 관련하여 알려진 문제점이 있습니까? 셋째, 아래의 부스트 코드는 무엇이며 끝없이 반복해야하는 이유는 무엇입니까? 여기 무슨 일이야, 집에 애들이 디버깅하려고하지 않는, 어쨌든

basic_managed_shared_memory (open_or_create_t, 
           const char *name, size_type size, 
           const void *addr = 0, const permissions& perm = permissions()) 
     : base_t() 
     , base2_t(open_or_create, name, size, read_write, addr, 
       create_open_func_t(get_this_pointer(), 
       ipcdetail::DoOpenOrCreate), perm) 
    {} 

: 아래

boost::interprocess::basic_managed_shared_memory<char, 
    boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, 
     boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>, 
     boost::interprocess::iset_index>::basic_managed_shared_memory<char,boo... 

또한 층은, 우리가 얻을

마지막으로 enter image description here

, 수백만 줄의 어셈블리 언어를 통해 한 단계 씩 수행 할 수있는 닌자 같은 기능을 사용하여 Visual C++ 2008의 사악한 디버거 제한을 깨고 코드를 발견했습니다. estion.

이것은 실제로 불고 있습니다 : create_device<FileBased>(dev....

여기에 몇 가지 상황 : managed_open_or_create_impl.h 라인 (351) ...

else if(type == DoOpenOrCreate){ 
     //This loop is very ugly, but brute force is sometimes better 
     //than diplomacy. If someone knows how to open or create a 
     //file and know if we have really created it or just open it 
     //drop me a e-mail! 
     bool completed = false; 
     while(!completed){ 
      try{ 
       create_device<FileBased>(dev, id, size, perm, file_like_t()); // <-- KABOOM! 
       created  = true; 
       completed = true; 
      } 
      catch(interprocess_exception &ex){ 
       if(ex.get_error_code() != already_exists_error){ 
        throw; 
       } 
       else{ 
        try{ 
        DeviceAbstraction tmp(open_only, id, read_write); 
        dev.swap(tmp); 
        created  = false; 
        completed = true; 
        } 
        catch(interprocess_exception &e){ 
        if(e.get_error_code() != not_found_error){ 
         throw; 
        } 
        } 
        catch(...){ 
        throw; 
        } 
       } 
      } 
      catch(...){ 
       throw; 
      } 
      thread_yield(); 
     } 
     } 
+1

자유로운 심술 얼굴에 +1. –

+0

여기에 흡수해야 할 것이 많지만, First-Chance 예외가 완전히 해롭다는 가능성을 고려 했습니까? –

+0

나는 약간의 편집을했고이 질문에서 매우 전문적이지 않은 것들을 제거했다. 나는 원래 버전을 읽어야했던 누구에게나 사과합니다. –

답변

2

나는 당신이 가지고있는 동일한 문제점을 가지고 있다고 생각합니다. "\ boost \ interprocess \ shared_memory_object.hpp"에서 "shared_memory_object :: priv_open_or_create"함수를 살펴보십시오. 이 함수의 맨 위에는 공유 메모리 파일을 삭제하는 함수 체인을 시작하는 또 다른 함수 호출 "create_tmp_and_clean_old_and_get_filename"이 있습니다. case 문의 시작 부분에있는 priv_open_or_create 함수에서 함수 호출을 더 낮게 이동했습니다. 나는 내가 부스트 1.48을 사용하고 있다고 생각한다. 여기에 수정이 기능의 최종 버전입니다 : 사람이 공식 채널을 알고 있다면

inline bool shared_memory_object::priv_open_or_create 
    (ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm) 
{ 
    m_filename = filename; 
    std::string shmfile; 
    std::string root_tmp_name; 

    //Set accesses 
    if (mode != read_write && mode != read_only){ 
     error_info err = other_error; 
     throw interprocess_exception(err); 
    } 

    switch(type){ 
     case ipcdetail::DoOpen: 
      ipcdetail::get_tmp_base_dir(root_tmp_name); 
      shmfile = root_tmp_name; 
      shmfile += "/"; 
      shmfile += filename; 
      m_handle = ipcdetail::open_existing_file(shmfile.c_str(), mode, true); 
     break; 
     case ipcdetail::DoCreate: 
      ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, shmfile); 
      m_handle = ipcdetail::create_new_file(shmfile.c_str(), mode, perm, true); 
     break; 
     case ipcdetail::DoOpenOrCreate: 
     ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, shmfile); 
      m_handle = ipcdetail::create_or_open_file(shmfile.c_str(), mode, perm, true); 
     break; 
     default: 
     { 
      error_info err = other_error; 
      throw interprocess_exception(err); 
     } 
    } 

    //Check for error 
    if(m_handle == ipcdetail::invalid_file()){ 
     error_info err = system_error_code(); 
     this->priv_close(); 
     throw interprocess_exception(err); 
    } 

    m_mode = mode; 
    return true; 
} 

BTW, 나는 시도하고이 확인 얻기 위해 통과 수 및 향상에 추가 날 내가 좋아하는 물건을 수정 싫어으로 알려 주시기 바랍니다 이것은 그것의 완전한 효과를 알지 못한다.

희망이 도움이됩니다.

+0

부스트 메일 링리스트는 Boost :: Interprocess의 저자가 이것을 게시하는 좋은 장소가 될 것이라고 생각한다. –

0

부스트는 모두 놀랍고 무서운 것들로 가득하다.

Windows에서 간단한 해결 방법은 문제를 중지하면 차이로 차례로 발생하는 것으로 나타납니다/당신은/불쾌한 충돌의 다양한 해결 문제를 중지하고, 충돌 한 종류의 수, 대신 managed_shared_memorymanaged_windows_shared_memory로 전환 될 수있다 Windows 파일 시스템 동작과 유닉스 파일 시스템 동작 사이에서, 특히 Windows에서 부스트 및 managed_shared_memory을 사용하면 Windows 파일 시스템 잠금 제한을 실행할 수 있습니다. 이 문제를 해결하기위한 노력이 Boost 1.53에서 완료되었지만 Boost 1.53을 사용하고 있으며 여전히이 문제가 있음을 알립니다.

Windows에서 일반 managed_shared_memory을 사용하면 클라이언트 또는 서버 응용 프로그램 수명보다 오래 지속됩니다. 이는 일부 사람들의 경우 바람직 할 수 있으므로 해결 방법은 해당 사람들을위한 진정한 해결책이 아닙니다.

그러나 필자는 필자가 실제로는 필요 없다고 생각 했었지만, 편리 할 것이라고 생각했지만 적어도 현재의 Windows 용 Boost 구현에서는 가치가있는 것보다 많은 고통을 겪었습니다.

또한 공유 메모리 파일 삭제가 위의 질문에서 경험 한 문제를 일으키는 경쟁 조건의 근본 원인 인 것으로 나타났습니다. 생성, 검사 및 삭제와 관련된 적절한 동기화는 시스템의 실제 구현에 필수적이며 특히 마스터 (서버)가 공유 메모리 파일을 삭제하는 경우 치명적인 문제가있는 것으로 보입니다 일부 클라이언트는 여전히 그것을 사용하고 있습니다. 잠금 + NTFS- 파일 시스템 엉망을 제거하려면 재부팅이 필요합니다.

실제 솔루션을 찾으면 게시 하겠지만 위의 정보는 다른 곳에서 찾을 수있는 것보다 많은 정보입니다. managed_shared_memory을주의하고 managed_windows_shared_memory을 사용하고 "영구 공유 메모리"아이디어 작업을 시도하는 것을 잊어 버리십시오. 오히려 비 지속 창 - managed_windows_shared_memory 만 사용하십시오. 내 응용 프로그램에서 managed_shared_memory 클래스를 유지하면서,이 문제를 해결

아마, 심지어 원시는 Win32 API 뮤텍스와 간 동기화 기본의 또 다른 수준의 managed_shared_memory 개체에 대한 모든 액세스를 포장 의미한다. 부스트는 비슷한 것을 할 수 있지만, 우발적 인 복잡성이 더 많이 생길 수 있습니다.

(제외 : I에게 일반적인 사용에 너무 많이 수행 된 그 템플릿의 모든 - 더 - 일을 생각 여기 뿐이야, 특히 부스트에서, 요즘?)

는 업데이트 2 :managed_shared_memory을 얼린 다른 방법을 찾았습니다. 그러면 사용하는 모든 앱이 정지됩니다. 나는 Boost로 교착 상태를 만드는 것이 그렇게 쉬운 일이 아니라는 것을 기대하지는 않았지만 꽤 쉽게 할 수 있습니다. 구현 내의 뮤텍스 코드는 관리되는 공유 메모리의 다른 사용자가 해제하지 않고 사라진 뮤텍스를 영원히 기다리는 동결 상태가됩니다. 결코 끝나지 않을 뮤텍스를 기다리는이 끝없는 수면은 지금까지 적어도 윈도우에서 몇 가지 심각한 디자인 결함을 세었던이 향상된 프로세스 간 구현의 또 다른 심층적 인 설계 결함입니다. 어쩌면 리눅스에서 아름답게 작동 할 수도 있습니다.

이 같은라는이 찾기() 메소드입니다 전시 코드 : 만

: 여기

boost::interprocess::managed_shared_memory * segment; 
    std::pair<MyType*, std::size_t> f = segment->find<MyType>(name); 

가 뮤텍스 교착 상태 (일명 무한 대기, 냉동 작업)에 대한 스택 추적입니다 솔루션은이 뮤텍스를 기다리고있는 모든 중지 된 프로세스를 중지하거나 종료 한 후에 공유 메모리 영역을 삭제하는 것입니다.

> myapp.exe!boost::interprocess::winapi::sched_yield() Line 998 C++ 
    myapp.exe!boost::interprocess::ipcdetail::thread_yield() Line 60 + 0xe bytes C++ 
    myapp.exe!boost::interprocess::ipcdetail::spin_mutex::lock() Line 71 C++ 
    myapp.exe!boost::interprocess::ipcdetail::spin_recursive_mutex::lock() Line 91 C++ 
    myapp.exe!boost::interprocess::interprocess_recursive_mutex::lock() Line 161 C++ 
    myapp.exe!boost::interprocess::scoped_lock<boost::interprocess::interprocess_recursive_mutex>::lock() Line 280 C++ 
    myapp.exe!boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index>::priv_get_lock(bool use_lock=true) Line 1340 C++ 
    myapp.exe!boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index>::priv_generic_find<char>(const char * name=0x00394290, boost::interprocess::iset_index<boost::interprocess::ipcdetail::index_config<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0> > > & index={...}, boost::interprocess::ipcdetail::in_place_interface & table={...}, unsigned int & length=1343657312, boost::interprocess::ipcdetail::bool_<1> is_intrusive={...}, bool use_lock=true) Line 854 + 0x11 bytes C++ 
    myapp.exe!boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index>::priv_find_impl<boost::container::map<AreaKeyType,DATA_AREA_DESC,std::less<AreaKeyType>,boost::interprocess::allocator<std::pair<AreaKeyType const ,DATA_AREA_DESC>,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index> > > >(const char * name=0x00394290, bool lock=true) Line 728 + 0x25 bytes C++ 
    myapp.exe!boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index>::find<boost::container::map<AreaKeyType,DATA_AREA_DESC,std::less<AreaKeyType>,boost::interprocess::allocator<std::pair<AreaKeyType const ,DATA_AREA_DESC>,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index> > > >(const char * name=0x00394290) Line 423 + 0x1e bytes C++ 
    myapp.exe!boost::interprocess::ipcdetail::basic_managed_memory_impl<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index,8>::find<boost::container::map<AreaKeyType,DATA_AREA_DESC,std::less<AreaKeyType>,boost::interprocess::allocator<std::pair<AreaKeyType const ,DATA_AREA_DESC>,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index> > > >(boost::interprocess::ipcdetail::char_ptr_holder<char> name={...}) Line 346 + 0x23 bytes C++ 
    myapp.exe!boost::interprocess::basic_managed_shared_memory<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index>::find<boost::container::map<AreaKeyType,DATA_AREA_DESC,std::less<AreaKeyType>,boost::interprocess::allocator<std::pair<AreaKeyType const ,DATA_AREA_DESC>,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index> > > >(boost::interprocess::ipcdetail::char_ptr_holder<char> name={...}) Line 208 + 0x10 bytes C++ 
    myapp.exe!CCommonMemory::AllocateOrFindAreaMap(const char * name=0x00394290) Line 128 C++ 
+0

언제든지 업데이트 2 부분을 수정 했습니까 ?? 내 소비자 코드가이 코드를 사용하면 무기한으로 잠자기가됩니다. MyDeque * Mydeque = segment.find ("dequeName"). – brownKnight

+0

Nope. 그렇게 독창적으로 작성된 모든 코드는 내가 읽을 수 없다는 것을 알았지 만, 내 코드베이스에서 올바른 해결책이 아닙니다. 멍청한 곳으로 바뀌었고 읽기가 어려웠습니다. DDE. 네. DDE. 20xx 년. –

+0

당신이 this.My 첫 번째 응용 프로그램은 Visual Studio를 사용하여 64 비트에서 만들어졌고 소비자 응용 프로그램이 32 비트 인 경우 잘 모르겠습니다. 나는 둘 다 64 빌드로 바꿨고 지금은 작동한다. 도움이 되셨기를 바랍니다. – brownKnight