0

わかりました、の使用に少し問題がありboost::fast_pool_allocatorます。

私が持っているコードは、への最初の数回の呼​​び出しで機能fast_pool_allocator::allocate(1)していますが、次のメッセージで失敗しています:

Engine.exe の 0x000000013fd0fe2d で未処理の例外: 0xC00000005: アクセス違反の読み取り場所 0x0000000000ffffff

コール スタック:

Engine.exe!boost::simple_segregated_storage<unsigned __int64>::malloc()  Line 104
Engine.exe!boost::pool<boost::default_user_allocator_new_delete>::malloc()  Line 223 
Engine.exe!boost::singleton_pool<boost::fast_pool_allocator_tag,128,boost::default_user_allocator_new_delete,boost::details::pool::win32_mutex,32>::malloc()  Line 59
Engine.exe!boost::fast_pool_allocator<EventDataSize,boost::default_user_allocator_new_delete,boost::details::pool::win32_mutex,32>::allocate(const unsigned __int64 n)  Line 229
Engine.exe!IEventData::operator new(unsigned __int64 size)  Line 46
etc...  

問題のブースト コードの行は、アロケーター ストレージ メカニズムが次のフリー チャンクを返そうとしているところにあるようで、フリー チャンクのリストからそれを削除しています。

void * malloc()
{
  void * const ret = first;

  // Increment the "first" pointer to point to the next chunk
  first = nextof(first); // <--- This is the line that is failing.
  return ret;
}

私のコードは次のようになります。

class EventDataSize
{
private:
    U8 dummyField[128];
};

class IEventData
{    
public:    
    void* operator new(size_t size)
    {       
        void* ptr = boost::fast_pool_allocator<EventDataSize>::allocate(1);
        if (!ptr)
            throw std::bad_alloc();
        return ptr;
    }

    void operator delete(void* ptr)
    {
        boost::fast_pool_allocator<EventDataSize>::deallocate((EventDataSize*)ptr, 1);
    }

// etc...
}

ご覧のとおり、このEventDataSizeクラスをダミーとして使用して、継承元のクラスにIEventData同じサイズ (たとえば 128 バイト) を割り当てて、プール アロケーターが継承を適切に処理できるようにしようとしています。

他の基本クラスで operator new を実装するために、まったく同じパターンを使用していますが、同じ問題は発生していないようです。

不思議なことに、配列のサイズを変更するとEventDataSize::dummyField問題は解消されます (または少なくとも、まだ発生していません) が、このような標準以下のソリューションには満足できません...なぜこのアロケーターが何をしているのか知りたいです。やっていること、間違っていること、そしてそれをうまく修正する方法を教えてください。

4

2 に答える 2

3

同じパターンを使用し、独自の ControlSize ダミー (これも 128 バイト) を使用する別の基本クラス IControl があるため、両方の fast_pool_allocators が内部で同じプール オブジェクトを使用していることに気付きました。

ただし、IControl のサブクラスの 1 つが 128 バイトを超えていました。したがって、問題なく割り当てられていましたが、プールのリンクされた空きチャンクのリストを上書きしていました。

本質的に、それはまさに Oo Tiib が話していた問題でしたが、コードのわずかに異なるセクションに移行しました。

Oo Tiibが示したように、bish-bash-boshの両方の場所でコードを修正しました。それは魅力のように機能します!

于 2012-09-10T17:31:20.497 に答える
2

自分の理論が (それが何であれ) 成り立つことを常にテストしてください。IEventData には 128 バイトで十分であるという理論があるようですが、サイズを無視してもよいですか? 先に進んでテストしてください:

void* operator new(size_t size)
{
    if ( size > sizeof( EventDataSize ) )
    {
       throw std::runtime_error("crappy idea, pal");
    }
    void* ptr = boost::fast_pool_allocator<EventDataSize>::allocate(1);
    if (!ptr)
        throw std::bad_alloc();
    return ptr;
}

私にとっては、128 バイトを超えるイベント データが存在する可能性が高いため、プール アロケーターのプール内のものを台無しにします。

于 2012-09-08T21:01:18.383 に答える