2012-10-12 45 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

相关问题