一類礦的有析像:指針的過早缺失通過共享指針
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)總是立即將新的結果分配給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;
}
};
在構造函數MergeMove()中'mergeIndex1'的初始值是什麼? – iammilind
很可能你的問題是'shared_from_this'。不過,請重新指出(1),不要使用'new'。使用'make_shared'。 –
你認爲第3點提到的「標準指南」在哪裏? ...從我看過的和讀過的,甚至Herb Sutter都說過'shared_ptr'可以通過引用安全地傳遞(特別是通過'const'引用)... – Jason