0

私のクラスには、次のようなデストラクタがあります。

virtual ~MergeMove()
{

    mergeIndex1=-1; // for debugging
    mergeIndex2=-1; // for debugging
}

別のクラスには、タイプ のメンバが含まれています。boost::shared_ptr<Move>ここで、Moveは のベースクラスですMergeMove。のデストラクタMoveは仮想です。

class Forest
{
     vector< boost::shared_ptr<Move> > moves;
     ....
}

私のコードがクラッシュした時点で、moves.at(i)->mergeIndex1=-1. デストラクタだけがそれを設定できると確信してい-1ます。また、valgrind はいくつかの無効な読み取りを報告します。私は 24 時間以上にわたって問題をデバッグしてきましたが、うまくいきませんでした。私は、shared_ptrs を使用するための標準的なガイドラインに従っていると思います。

1) new の結果は常にすぐに shared_ptr に割り当てられます。生のポインターはありません。

this2) を期待する関数に渡すときにshared_ptr、 を使用しshared_from_this()ました。しかし、私は*this参照を取るいくつかの関数に渡しました - 私はそれがうまくいくはずだと思います。

何が問題なのですか?gcc バージョン 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5.1) を使用しています。既知のバグはありますか? さらにデバッグするにはどうすればよいですか?

これはvalgrindからの出力です...これは時期尚早の削除を確認します:

==28242== Invalid read of size 8
==28242==    at 0x5CAAFA: boost::shared_ptr<Symbol>::get() const (shared_ptr.hpp:424)
==28242==    by 0x5E0160: bool boost::operator==<Symbol, Symbol>(boost::shared_ptr<Symbol> const&, boost::shared_ptr<Symbol> const&) (shared_ptr.hpp:481)
==28242==    by 0x5C5851: MergeMove::applyMove(Forest&) (mcmcParsh.h:1022)
==28242==    by 0x5C43C4: Forest::applyMove(int) (mcmcParsh.h:704)
==28242==    by 0x5C4408: Forest::applyMoveToClone(int) (mcmcParsh.h:709)
==28242==    by 0x5C46C1: Forest::genMoveAndApplyToClone() (mcmcParsh.h:753)
==28242==    by 0x5C64D3: BeamSearch::sampleNextBeam() (mcmcParsh.h:1414)
==28242==    by 0x5C65F9: BeamSearch::runBeamSearch() (mcmcParsh.h:1431)
==28242==    by 0x58F2CA: find_most_violated_constraint_marginrescaling(pattern, label, structmodel*, struct_learn_parm*) (svm_struct_api.cpp:221)
==28242==    by 0x5AC5FE: find_most_violated_constraint(svector**, double*, example*, svector*, long, structmodel*, struct_learn_parm*, double*, double*, long*) (svm_struct_learn.cpp:944)
==28242==    by 0x5AB339: svm_learn_struct_joint(sample, struct_learn_parm*, learn_parm*, kernel_parm*, structmodel*, int) (svm_struct_learn.cpp:719)
==28242==    by 0x5A62F5: main (svm_struct_main.cpp:81)
==28242==  Address 0x31461568 is 152 bytes inside a block of size 200 free'd
==28242==    at 0x4C27A83: operator delete(void*) (vg_replace_malloc.c:387)
==28242==    by 0x5C4EC0: MergeMove::~MergeMove() (mcmcParsh.h:971)
==28242==    by 0x60A0BA: void boost::checked_delete<MergeMove>(MergeMove*) (checked_delete.hpp:34)
==28242==    by 0x63A299: boost::detail::sp_counted_impl_p<MergeMove>::dispose() (sp_counted_impl.hpp:78)
==28242==    by 0x5AFBD9: boost::detail::sp_counted_base::release() (sp_counted_base_gcc_x86.hpp:145)
 ==28242==    by 0x5AFC9C: boost::detail::shared_count::~shared_count() (shared_count.hpp:217)
==28242==    by 0x5C367D: boost::shared_ptr<Move>::~shared_ptr() (shared_ptr.hpp:169)
==28242==    by 0x61EA5F: void std::_Destroy<boost::shared_ptr<Move> >(boost::shared_ptr<Move>*) (stl_construct.h:83)
==28242==    by 0x615EFF: void std::_Destroy_aux<false>::__destroy<boost::shared_ptr<Move>*>(boost::shared_ptr<Move>*, boost::shared_ptr<Move>*) (stl_construct.h:93)
==28242==    by 0x609806: void std::_Destroy<boost::shared_ptr<Move>*>(boost::shared_ptr<Move>*, boost::shared_ptr<Move>*) (stl_construct.h:116)
==28242==    by 0x5F57C4: void std::_Destroy<boost::shared_ptr<Move>*, boost::shared_ptr<Move> >(boost::shared_ptr<Move>*, boost::shared_ptr<Move>*, std::allocator<boost::shared_ptr<Move> >&) (stl_construct.h:142)
==28242==    by 0x5DF807: std::vector<boost::shared_ptr<Move>, std::allocator<boost::shared_ptr<Move> > >::~vector() (stl_vector.h:313)

ここにベースクラスのコードがあります

class Move
{
 private:
double costDelta;
double transProb;
LOSS_MAP_TYPE addMap;
LOSS_MAP_TYPE delMap;
protected:
bool transProbSet;
bool applied;


void setTransProbFromDelta()
{
    transProb=exp(costDelta/10.0);
    transProbSet=true;
}

public:
typedef  boost::shared_ptr<Move> SPtr;

virtual Move::SPtr clone()=0;
void applylabelMapDelta( LOSS_MAP_TYPE & lab)
{
    subtractLabelmap(delMap,lab);

    appendLabelmap(addMap,lab);
}

typedef SupportComplex<Floor> SCENE_TYPE;
void resetCostDelta()
{
    costDelta=0;
}

void adjustCostDeltaForNodeAddition(Symbol::Ptr newNode, Forest & cfor);
void adjustCostDeltaForNodeRemoval(Symbol::Ptr remNode, Forest & cfor);
virtual void adjustCostDeltaByLossForNodeAddition(Symbol::Ptr newNode, Forest & cfor);
virtual void adjustCostDeltaByLossForNodeRemoval(Symbol::Ptr remNode, Forest & cfor);

virtual string toString()=0;
double getCostDelta()
{
    return costDelta;
}

Move()
{
    transProb=false;
    costDelta=0;
    applied=false;
}

virtual bool moveCreationSucceded()
{
    return true;
}


virtual void applyMove(Forest & cfor)=0;
/**
 * 
 * @return Q(f',f) where f' is the forest which will be generated when
 * applyMove is called on f
 */
virtual double getTransitionProbUnnormalized()
{
    assert(transProbSet);
    return transProb;
}

virtual bool isInvalidatedOnDeletion(int index)=0;
virtual bool handleMove(int oldIndex, int newIndex)=0;
virtual ~Move() {}
};

Symbol::Ptrもshared_ptrです

class MergeMove: public Move
{
int mergeIndex1,mergeIndex2;
Symbol::Ptr mergeNode1,mergeNode2; // store nodes also for additional safety check
RulePtr mergeRule;
NonTerminal_SPtr mergeResult;

public:
virtual Move::SPtr clone()
{
    boost::shared_ptr<MergeMove> ret (new MergeMove(*this));
    cerr<<"mmclon:"<<toString()<<":"<<this<<"->"<<ret.get()<<endl;
    assert(ret->mergeIndex1!=-1);
    assert(ret->mergeIndex2!=-1);
    return ret;
}
typedef  boost::shared_ptr<MergeMove> SPtr;

virtual bool moveCreationSucceded()
{
    return (mergeResult!=NULL);
}

vector<Symbol::Ptr> marshalParams(RulePtr mergeRule)
{
    vector<Symbol::Ptr> nodes;
    if(mergeRule->getChildrenTypes().at(0)==string(typeid(*mergeNode1).name()))
    {
          nodes.push_back(mergeNode1);
          nodes.push_back(mergeNode2);
    }
    else
    {            
        assert(mergeRule->getChildrenTypes().at(0)==string(typeid(*mergeNode2).name()));
          nodes.push_back(mergeNode2);
          nodes.push_back(mergeNode1);            
    }
    return nodes;
}

virtual ~MergeMove()
{

    if(moveCreationSucceded())
            cerr<<"mmdel:"<<toString()<<":"<<this<<endl;
    mergeIndex1=-1; // for debugging
    mergeIndex2=-1; // for debugging
}

MergeMove(Forest & cfor, int mergeIndex1, int mergeIndex2, RulePtr mergeRule)
{

    assert(mergeIndex1>=0);
    assert(mergeIndex2>=0);
    this->mergeIndex1=mergeIndex1;
    this->mergeIndex2=mergeIndex2;
    this->mergeRule=mergeRule;
    assert(mergeRule->getChildrenTypes().size()==2);

    assert(mergeIndex1!=mergeIndex2);

    mergeNode1=cfor.getTree(mergeIndex1);
    mergeNode2=cfor.getTree(mergeIndex2);

    assert(cfor.getTree(mergeIndex1)==mergeNode1);
    assert(cfor.getTree(mergeIndex2)==mergeNode2);
    mergeResult=mergeRule->applyRuleMarshalledParams(marshalParams(mergeRule));


    if(mergeResult==NULL)
    {
        return;
    }

    mergeResult->declareOptimal(false);

            adjustCostDeltaForNodeAddition(mergeResult,cfor);
    adjustCostDeltaForNodeRemoval(mergeNode1,cfor);
    adjustCostDeltaForNodeRemoval(mergeNode2,cfor);
    setTransProbFromDelta();
            cerr<<"mmcreat:"<<toString()<<endl;

}

virtual string toString()
{
    return mergeNode1->getName()+","+mergeNode2->getName()+"->"+mergeResult->getName();
}

virtual void applyMove(Forest & cfor)
{
    applied=true;
    // safety checks ... in the face of index updates
    assert(cfor.getTree(mergeIndex1)==mergeNode1);
    assert(cfor.getTree(mergeIndex2)==mergeNode2);


    cfor.deleteTree(mergeIndex1);// max to reduce #index updates in moves

    assert(cfor.getTree(mergeIndex2)==mergeNode2);

    cfor.replaceTree(mergeIndex2,mergeResult); // isSpanDisjo
}


virtual bool isInvalidatedOnDeletion(int index)
{
    if(index==mergeIndex1 || index==mergeIndex2)
        return true;


    return false;
}

virtual bool handleMove(int oldIndex, int newIndex )
{
    bool changed=false;


    if(mergeIndex1 == oldIndex)
    {
        mergeIndex1 = newIndex;
        changed=true;
    }

    if(mergeIndex2 == oldIndex)
    {
        mergeIndex2 = newIndex;
        changed=true;
    }



    return changed;
}
};
4

1 に答える 1

0

セグメンテーション違反を修正したようです。また、valgrind は無効な読み取りを報告しなくなりました。しかし、以前にセグメンテーション違反が発生した理由はわかりません。おそらく、質問の 2 番目のポイントの 2 行目の私の仮定は間違っていました。

以前は、Move::applyMove は次のように宣言されていました。

virtual void applyMove(Forest & cfor)=0;

ラッパーを作成し、すべての呼び出しがラッパーを使用するようにしました。

virtual void applyMove(boost::shared_ptr<Forest> cfor)
{
    applyMove(*cfor);
}

私のコード内のすべての Forest オブジェクトは、によって動的に割り当てられ、管理されます。shared_ptr

それに応じて、私の Forest::applyMove(int) はから変更されました

void applyMove(int index)
{
    Move::SPtr selMove=moves.at(index);
    selMove->applyMove(*this);
}

void applyMove(int index)
{
    Move::SPtr selMove=moves.at(index);
    selMove->applyMove(shared_from_this());
}
于 2012-05-29T05:51:17.987 に答える