2017-05-06 33 views
-1

我正在研究解析器,並且遇到麻煩的段錯誤。模板子類析構函數中的Segfault

解析器返回一個解析的變體,該解析的變體反過來返回用於傳遞解析結果的變體。在刪除指向基類的指針時發生段錯誤。

這裏是我的基類:

class ParsedVariant { 

protected: 
    ParsedVariant() {} 

public: 
    virtual ~ParsedVariant() {} 

private: 
    ParsedVariant(const ParsedVariant& other); 
    ParsedVariant& operator= (const ParsedVariant& other); 

public: 
    virtual const std::string& getName() const=0; 
    // Get the final variant. 
    virtual Variant *getVariant()=0; 

}; 

這裏是模板的子類:

template<typename S, class V> class ParsedScalar : public ParsedVariant { 

public: 
    ParsedScalar(const S& s, const std::string& n) : sval(s), name(n) {} 
    ~ParsedScalar() {} 

private: 
    ParsedScalar(const ParsedScalar& other); 
    ParsedScalar& operator= (const ParsedScalar& other); 

public: 
    const std::string& getName() const { return name; } 
    Variant *getVariant() { return new V(sval, name); } 

private: 
    S sval; 
    std::string name; 

}; 

在S模板參數將是一個標量型(INT,布爾,雙等) 。 V模板參數將是最終的變體類。

他們使用這樣的:在底層調用析構函數ParsedVariant釋放發生

ParsedVariant *functionA() { 

    int n; 
    // Some work here. 
    return new ParsedScalar<int, IntegerVariant>(n, "varname"); 

} 

void functionB() { 

    ParsedVariant *var = functionA(); 
    // Do some work. 
    delete var; <== SEGV happens here. 

} 

的段錯誤。我在模板中使用哪種標量類型並不重要,它們都是段錯誤。編譯器是g ++ 4.8.3,我正在使用-std = C++ 11標誌。我覺得這是顯而易見的,但我似乎錯過了它。任何幫助表示讚賞。

+2

添加代碼以創建完整程序後無法重現:http://coliru.stacked-crooked.com/a/1d06de612092e31c錯誤出現在您未顯示的代碼中。 – aschepler

+1

顯示的代碼沒有問題,因此該錯誤出現在未顯示的代碼中。爲了確定答案,需要[mcve]。僅僅因爲一個C++程序在某一行中崩潰並不意味着這是該錯誤所在。你的bug可以在任何地方。歡迎來到C++ ... –

+0

你的調試器說什麼?你的[MCVE]在哪裏?基本的東西。 –

回答

0

我解決了這個問題,但原因很奇怪;

class ScalarParser { 

    public: 
     ScalarParser(); 
     ~ScalarParser(); 

    public: 
     ParsedVariant *getParsed() { return parsed; } 
     void parse(std::istream& in); // Produces parsed 

    private: 
     ParsedVariant *parsed; 
}; 

ScalarParser::~ScalarParser() { 
    delete parsed; 
} 

void Document::parseScalar(std::istream& in) { 

    ScalarParser parser; 
    parser.parse(in); <== produces valid ParsedVariant 
    ParsedVariant *parsed = parser.getParsed(); <== ~ScalarParser called after this line 
    push(parsed->getVariant()); <== SEGV 

} 

該段錯誤消失,如果我註釋掉ScalarParser析構函數中刪除。這也會導致段錯誤消失。

void Document::parseScalar(std::istream& in) { 

    ScalarParser *parser = new ScalarParser; 
    parser->parse(in); 
    ParsedVariant *parsed = parser->getParsed(); 
    push(parsed->getVariant()); 
    delete parser; 

} 

這也解決了這個問題。

void Document::parseScalar(std::istream& in) { 

    std::unique_ptr<ScalarParser> parser(new ScalarParser); 
    parser->parse(in); 
    ParsedVariant *parsed = parser->getParsed(); 
    push(parsed->getVariant()); 

} 

這是一個解析器,所以代碼很大且很複雜。其中一些也是專有的,所以這是我能做的最好的。我不確定這是否是一個編譯器錯誤。我會一直捅它以獲取更多信息。感謝您的迴應。

+0

*我不確定這是否是一個編譯器錯誤* - 我敢打賭,這不是編譯器錯誤。編譯器在大型程序中使用的相對簡單的代碼中不會出現這樣的錯誤。編譯器不會感到困惑,因爲代碼「龐大而複雜」。一個人可能會感到困惑,但不是編譯器。 – PaulMcKenzie