2

以前、boost-interprocess の質問をして、使用をやめると誓ったのですが、残念ながら、私は立ち往生しており、これが機能することが本当に必要です。だから私はまだそれと戦っています。

を割り当ててすぐに破棄すると、奇妙なクラッシュboost::interprocess::managed_windows_shared_memory::segment_managerが発生しますが、これはビルド中の Windows DLL プロジェクト内でのみ発生します。Boostに報告する方法としてスタンドアロンプ​​ログラムで再現しようとしましたが、自分のDLL以外では再現しません。

また、オブジェクトを通常どおりに作成し、より適切なタイミングで解放したときにも発生しますが、ここで示そうとしているのは、Boost がオブジェクトを作成できることと、時間が経っても状態が変化していないことです。ヒープですが、Boost はクラッシュせずにこのオブジェクトを解放することはできません。

これは、スタンドアロンのサンプル プロジェクトでは発生しません (発生するかどうかを確認するためにビルドしました) が、クラッシュしているプロジェクトで他のコードが実行されていることは認識していません。

本当に奇妙なのは、DLLMain 関数からクラッシュしていることです。これは、DLLMain 関数で最初にこの C++ ブースト オブジェクトを割り当ててから破棄することです。このブースト オブジェクトの何かが奇妙で、大量のもの (赤黒ツリー) を作成し、それ自体をクリーンアップすることさえできません。

以下のコードは、問題を再現するのに十分ではありません。DLL に何か問題があり、結果の Boost オブジェクトを自分自身で作成できるようにしますが、シャットダウン時にクラッシュします。

// BoostDllMain.cpp :
//
//  Attempt to demonstrate an insane situation in my code, where
//  boost::interprocess::managed_windows_shared_memory::segment_manager 
//  can be created, but freeing it causes access violations. The context
//  for object creation and destruction is DLL load and unload time.



#include "stdafx.h"

#include <objbase.h>
#include <windows.h>



#ifdef PERSISTENT_SHARED_MEM
#include <boost/interprocess/managed_shared_memory.hpp>
#else
#include <boost/interprocess/managed_windows_shared_memory.hpp>
#endif

#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <functional>
#include <utility>

#define SHARED_AREA_SIZE (1024*1024*8)  // 8 megabytes of shared memory should be enough to store more than 60K data points. 
                                    // In testing using current structure sizes, allocation Failed at the 61678th 
                                    // data point item when set to this value.



#ifdef PERSISTENT_SHARED_MEM
typedef boost::interprocess::managed_shared_memory                  mgr;
typedef boost::interprocess::managed_shared_memory::segment_manager seg;
#else
typedef boost::interprocess::managed_windows_shared_memory                  mgr;
typedef boost::interprocess::managed_windows_shared_memory::segment_manager seg;
#endif

using namespace boost::interprocess;

mgr *       segment1;
mgr *       segment2;

void Init(void) {

// Tweak C Runtime Debug Heap Flags.
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
tmpFlag |= _CRTDBG_CHECK_CRT_DF;
_CrtSetDbgFlag( tmpFlag );  

      segment1 = new mgr(   open_or_create
                           , "ED3_MEMORY" // This is a global memory area name

                           , SHARED_AREA_SIZE );    
      segment2 = new mgr(   open_or_create
                           , "ED3_MEMORY" // This is a global memory area name

                           , SHARED_AREA_SIZE );  
}

void Cleanup(void) {

     delete segment1;
     segment1 = NULL;


     delete segment2;
     segment2 = NULL;


}

//
extern "C"
BOOL WINAPI DllMain(IN HANDLE hInstance, IN DWORD dwReason, IN VOID *pReserved )
{



    switch ( dwReason )
    {
    case DLL_PROCESS_ATTACH:

        Init();

        break;

    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
        break;

    case DLL_PROCESS_DETACH:

        Cleanup();


        break;

    default:
        break;
    }

    return(1);
}

要するに、managed_windows_shared_memoryあなたが作成したオブジェクトは、すぐにきれいに(アクセス違反なしで)破壊することさえできません。これは、DLLがロードされたときにオブジェクトを作成し、DLLアンロードします。

これがスタックのトレースバックです。少しでも理解できれば、あなたはおそらく人間ではなく C++ コンパイラーですが、とにかくここにあります。

>   mydll.dll!boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void,int,unsigned int,0> >,int,unsigned int,0>::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void,int,unsigned int,0> >,int,unsigned int,0>(const boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void,int,unsigned int,0> >,int,unsigned int,0> & ptr={...})  Line 272 + 0xf bytes   C++
    mydll.dll!boost::intrusive::compact_rbtree_node_traits_impl<boost::interprocess::offset_ptr<void,int,unsigned int,0> >::get_left(const boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void,int,unsigned int,0> >,int,unsigned int,0> & n={...})  Line 142 + 0x1d bytes   C++
    mydll.dll!boost::intrusive::detail::tree_algorithms<boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1> >::dispose_subtree<boost::intrusive::detail::node_disposer<boost::intrusive::detail::null_disposer,boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int>,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,1,boost::intrusive::default_tag,3>,std::less<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int> >,unsigned int,1> > > >(boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void,int,unsigned int,0> >,int,unsigned int,0> x={...}, boost::intrusive::detail::node_disposer<boost::intrusive::detail::null_disposer,boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int>,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,1,boost::intrusive::default_tag,3>,std::less<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int> >,unsigned int,1> > > disposer={...})  Line 1298 + 0xd bytes  C++
    mydll.dll!boost::intrusive::detail::tree_algorithms<boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1> >::clear_and_dispose<boost::intrusive::detail::node_disposer<boost::intrusive::detail::null_disposer,boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int>,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,1,boost::intrusive::default_tag,3>,std::less<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int> >,unsigned int,1> > > >(const boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void,int,unsigned int,0> >,int,unsigned int,0> & header={...}, boost::intrusive::detail::node_disposer<boost::intrusive::detail::null_disposer,boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int>,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,1,boost::intrusive::default_tag,3>,std::less<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int> >,unsigned int,1> > > disposer={...})  Line 577 + 0x15 bytes   C++
    mydll.dll!boost::intrusive::rbtree_algorithms<boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1> >::clear_and_dispose<boost::intrusive::detail::node_disposer<boost::intrusive::detail::null_disposer,boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int>,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,1,boost::intrusive::default_tag,3>,std::less<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int> >,unsigned int,1> > > >(const boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void,int,unsigned int,0> >,int,unsigned int,0> & header={...}, boost::intrusive::detail::node_disposer<boost::intrusive::detail::null_disposer,boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int>,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,1,boost::intrusive::default_tag,3>,std::less<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int> >,unsigned int,1> > > disposer={...})  Line 451 + 0x16 bytes C++
    mydll.dll!boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int>,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,1,boost::intrusive::default_tag,3>,std::less<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int> >,unsigned int,1> >::clear_and_dispose<boost::intrusive::detail::null_disposer>(boost::intrusive::detail::null_disposer disposer={...})  Line 1006 + 0x26 bytes C++
    mydll.dll!boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int>,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,1,boost::intrusive::default_tag,3>,std::less<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int> >,unsigned int,1> >::clear()  Line 987  C++
    mydll.dll!boost::intrusive::detail::clear_on_destructor_base<boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int>,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,1,boost::intrusive::default_tag,3>,std::less<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int> >,unsigned int,1> > >::~clear_on_destructor_base<boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int>,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,1,boost::intrusive::default_tag,3>,std::less<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int> >,unsigned int,1> > >()  Line 27  C++
    mydll.dll!boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int>,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,1,boost::intrusive::default_tag,3>,std::less<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int> >,unsigned int,1> >::~rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int>,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,1,boost::intrusive::default_tag,3>,std::less<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int> >,unsigned int,1> >()  Line 284 + 0x14 bytes  C++
    mydll.dll!boost::intrusive::set_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int>,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,1,boost::intrusive::default_tag,3>,std::less<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int> >,unsigned int,1> >::~set_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int>,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,1,boost::intrusive::default_tag,3>,std::less<boost::interprocess::ipcdetail::intrusive_value_type_impl<boost::intrusive::detail::generic_hook<boost::intrusive::get_set_node_algo<boost::interprocess::offset_ptr<void,int,unsigned int,0>,1>,boost::intrusive::default_tag,1,3>,char,unsigned int> >,unsigned int,1> >()  Line 139 + 0x14 bytes    C++
    mydll.dll!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> > >::~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> > >()  + 0x14 bytes    C++
    mydll.dll!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>::header_t::~header_t()  + 0x3d bytes    C++
    mydll.dll!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>::~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>()  + 0x3d bytes  C++
    mydll.dll!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>::`scalar deleting destructor'()  + 0x14 bytes   C++

要するに、私は持っています

A. この DLL のコンテキストで他のコードがまだ実行されていないため、私が作成したコードからのヒープの破損を除外しました。他のオブジェクトは作成および解放できますが、問題ありません。この DLL で作成または破棄できないのは、この Boost オブジェクトだけです。

B. DLL プロジェクトは、「マルチスレッド デバッグ DLL」として設定されたコード生成でコンパイルされています。

C. boost::interprocess::managed_windows_shared_memory::segment_manager常に同じ場所でデストラクタがクラッシュします。ランダムではありません。その場所はmydll.dll!boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<....

D. Windows 共有メモリから、この DLL コンテキストで、単に と呼ばれる他のオプションに切り替えると、WMI 呼び出しshared_memoryでフリーズ/デッドロックします。get_last_bootup_timeこれは win32_api.hpp の関数で、Window WMI 関数呼び出しを実行し、クラスWin32_OperatingSystemプロパティを読み取ろうとしていますLastBootUpTime

E. 私は DLL と Boost がお互いに好きではないと考え始めていますCoInitialize.

このクレイジーなものをどのようにデバッグしますか?

4

1 に答える 1

3

DllMain には、この関数へのエントリ時にローダー ロックを保持しているという事実に基づいて、いくつかのかなり厳しい制限があり、DllMain にライブラリをロードすると、ライブラリ ローダーはライブラリの依存関係を適切に計算しません。

これらすべてについて非常に注意が必要なのは、ローダー ロックを直接的または間接的に保持できないことです。たとえば、LoadLibrary を呼び出したり、他のスレッドと同期したり、CreateThread を呼び出したり、CRT からメモリ管理関数を呼び出したり、User32 から何かを呼び出したりすることはできません。こちら (Microsoft)の DLL ベスト プラクティス ガイドを読み、ドキュメントの最後にある参考文献を参照してください。

簡単な答え: DllMain にこのようなものをロードしないでください。

于 2013-06-18T23:01:59.133 に答える