2012-05-29 119 views
0
保持

一類礦的有析像:指針的過早缺失通過共享指針

virtual ~MergeMove() 
{ 

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

另一類包含boost::shared_ptr<Move>類型,其中MoveMergeMove的基類的成員。 Move的析構函數是虛擬的。

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

在我的代碼崩潰的時候,我發現moves.at(i)->mergeIndex1=-1。 我很確定只有析構函數可以將它設置爲-1。而且,valgrind報告了一些無效的讀取。 我一直在調試超過24小時的問題...沒有運氣。 我認爲我遵循了使用shared_ptrs的標準指南。

1)總是立即將新的結果分配給shared_ptr。沒有原始的指針。

2)當通過this函數期望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; 
} 
}; 
+0

在構造函數MergeMove()中'mergeIndex1'的初始值是什麼? – iammilind

+1

很可能你的問題是'shared_from_this'。不過,請重新指出(1),不要使用'new'。使用'make_shared'。 –

+1

你認爲第3點提到的「標準指南」在哪裏? ...從我看過的和讀過的,甚至Herb Sutter都說過'shared_ptr'可以通過引用安全地傳遞(特別是通過'const'引用)... – Jason

回答

0

看起來像我修復了段錯誤。此外,valgrind不再報告無效的讀取。但我不確定爲什麼它更早地進行了分割。也許,我在這個問題的第二點第二行中的假設是錯誤的 - 「但是我已經把這個傳遞給了一些參照的函數 - 我想它應該沒問題。」

以前,移動:: applyMove被宣佈爲

virtual void applyMove(Forest & cfor)=0; 

我做了一個包裝,並確保所有電話使用包裝。

virtual void applyMove(boost::shared_ptr<Forest> cfor) 
{ 
    applyMove(*cfor); 
} 
在我的代碼

所有的森林對象是動態分配的,並通過shared_ptr

相應管理,我的森林:: 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()); 
}