模板化子类析构函数中的Segfault

时间:2017-05-06 23:49:09

标签: c++ g++

我正在使用解析器,而且我遇到了麻烦的段错误。

解析器返回一个已解析的变体,该变体又返回用于传递解析结果的变体。删除指向基类的指针时会发生段错误。

这是我的基类:

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,bool,double等)。 V模板参数将是最终的变体类。

它们的用法如下:

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.

}

在基础调用free中的ParsedVariant析构函数中发生了段错误。我在模板中使用哪种标量类型并不重要,它们都是段错误。编译器是g ++ 4.8.3,我使用-std = c ++ 11标志。我觉得这很明显,但我似乎错过了它。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分: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());

}

这是一个解析器,因此代码很大且复杂。其中一些也是专有的,所以这是我能做的最好的。我不确定这是否是编译器错误。我会继续戳它以获取更多信息。感谢您的回复。