2012-10-12 85 views
2

我需要編寫一些類來在我的代碼中實現無上下文文法。 CFG具有格式「左側 - >右側」的生產規則。他們實現如下:爲什麼我的迭代器指向null,但只是有時?

class GrammarProduction{ 

    public: 

    Nonterminal mLhs; 
    std::vector<GrammarSymbol*> mRhs; 

我想將我的生產規則存儲在一個std :: set,以確保沒有人可以添加重複的規則。 爲了進行重複檢測工作,我爲語法生成實現了運算符<,如下所示。

bool GrammarProduction::operator<(const GrammarProduction& other) const{ 
    if (mLhs < other.Lhs()) return true; 
    if (mRhs.size() < other.Rhs().size()) return true; 
    std::vector<GrammarSymbol*>::const_iterator it1, it2; 
    it2 = other.Rhs().begin(); 
    for(it1 = mRhs.begin(); it1 != mRhs.end(); it1++){ 
    std::cout << (*it1) << std::endl; 
    std::cout << (*it2) << std::endl; 
    if(**it1 < **it2) return true; 
    it2++; 
    } 
    return false;  
} 

運行這段代碼讓我在行

if(**it1 < **it2) return true; 

因爲指針* IT2是空分割故障。但是,如果我將打印* it2的行更改爲

std::cout << (*it2) << other.Str() << std::endl; 

它工作得很好,* it2不爲空。我不知道這是爲什麼,任何意見將不勝感激。 如果需要發佈被調用的函數,我會這樣做。我沒有,因爲我希望這個問題不重要,它會是一個相當大的數量(至少對於一個職位而言)。

編輯:我已經縮小的問題,並把它歸結爲這個

bool GrammarProduction::operator<(const GrammarProduction& other) const{ 
    std::vector<GrammarSymbol*>::const_iterator it1, it2; 

    it1 = mRhs.begin(); 
    std::cout << "it1:" << std::endl; 
    std::cout << (*(mRhs.begin()))->Str() << std::endl; //output (1,2,2) 
    std::cout << (*it1)->Str() << std::endl; //output (1,2,2) 

    it2 = other.Rhs().begin(); 
    std::cout << "it2:" << std::endl; 
    std::cout << (*(other.Rhs().begin()))->Str() << std::endl; //output (1,2,2) 
    std::cout << (*it2)->Str() << std::endl; //Segmentation Fault 

    //do whatever 
    return false; 
} 
+0

提示:您可能想檢查'it2 == other.Rhs()。end()'。 – Xeo

+0

打我吧@Xeo。您可能會繼續超過其他大小.Rhs –

+0

不,這並不能解釋如何打印other.Str()會解決此問題。迭代器不能溢出,因爲「if(mRhs.size() Shal

回答

2

您正在調用未定義的行爲。由於您的Rhs()功能的價值返回矢量,它摧毀了充分表達的末尾:

//   vvvvv -- created here 
it2 = other.Rhs().begin(); 
//   gone here --^

這使得it2一個晃來晃去的迭代器,這是基本一致的懸擺指針。解引用這個迭代器會導致UB。要修復,請將返回類型作爲參考:

std::vector<GrammarSymbol*>& Rhs(){ return mRhs; } // depending on your needs 
std::vector<GrammarSymbol*> const& Rhs() const{ return mRhs; } 
+0

非常感謝! – Shal

1
if(**it1 < **it2) return true; 
it2++; 

是不是很好,因爲在你的循環,如果IT2達到列表的末尾,你不檢查。

版本應該工作將是:

bool GrammarProduction::operator<(const GrammarProduction& other) const{ 
    if (mLhs < other.Lhs()) return true; 
    if (mRhs.size() < other.Rhs().size()) return true; 
    std::vector<GrammarSymbol*>::const_iterator it1, it2; 
    it2 = other.Rhs().begin(); 
    it2End = other.Rhs().end(); 
    for(it1 = mRhs.begin(); it1 != mRhs.end(); it1++){ 
    std::cout << (*it1) << std::endl; 
    if (it2 == it2End) return true; 
    std::cout << (*it2) << std::endl; 
    if(**it1 < **it2) return true; 
    it2++; 
    } 
    return false; 

}

+0

感謝您的回答!不幸的是,這不可能是問題,你的代碼也無法工作。 「if(mRhs.size() Shal

2

您應該檢查在循環it2 == other.Rhs().end()。如果將迭代器遞增到最後一個元素,則解除引用是無效的,並且可能會導致分段錯誤。

+0

感謝您的回答! 「if(mRhs.size() Shal

相關問題