永远挂着析构函数

时间:2017-12-19 20:44:11

标签: c++

注释掉一些从未执行过的函数定义,但修复了它。怎么样?

完整的最小示例我最终删除了以下不相关的代码。

int main() {
    auto tList = tokenize();
    tList.front()->~Token();  //hangs forever if the code 10 lines above is not commented, normally I'll have pop_front() here
    cout << "never gets printed";
    return 0;
}

通常我会

tList.pop_front() 

而不是

tList.front()->~Token();

它只是为了更明确地展示它

承诺的代码:(也在https://gist.github.com/anonymous/3b8fa11e90c617b35623ba5432050c3e#file-main-cpp-L68) tokenizer.h

#include <list>
#include <memory>

using namespace std;

#ifndef SGREP_TOKENIZER_H
#define SGREP_TOKENIZER_H


class Token {
public:
    virtual ~Token() = default;

    virtual bool isChar() const {
        return false;
    }

};


using TTokenList = list<unique_ptr<Token>>;


TTokenList tokenize ();

#endif //SGREP_TOKENIZER_H

tokenizer.cpp

#include <iostream>
#include <cctype>
#include <string>

#include "tokenizer.h"

using namespace std;


class Char : public Token {
    char value;
public:
    Char (char value) : value(value){};

    bool isChar() const override {
        return true;
    }

};


TTokenList tokenize () {
    TTokenList tList;

    tList.push_back(make_unique<Char>('h'));

    return tList;
}

的main.cpp

#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <exception>

#include "tokenizer.h"

using namespace std;


class SyntaxError : public exception {};


class Regex {
public:
    virtual size_t match_part(const string& str, size_t begin, size_t maxLen, vector<size_t>& groups) = 0;  // groups is a vector of begin,end indices of matched groups (ParenRegexes) (to be able to recreate substrings)
    virtual ~Regex() = default;
};


class Char : public Regex  {
protected:
    vector<char> characterRanges;  // pairs -> lower and upper inclusive bound of matching a character (even lower, odd upper), size is always divisible by 2
public:
    Char(TTokenList& t, size_t& groupCount) {}

    size_t match_part(const string& str, size_t begin, size_t maxLen, vector<size_t>& groups) override {
        return 1;
    }
};


class SeqRegex: public Regex {
    unique_ptr<Regex> a;
public:
    SeqRegex(TTokenList& t, size_t& groupCount);

    size_t match_part(const string& str, size_t begin, size_t maxLen, vector<size_t>& groups) override {  // maxLen by nemelo byt 0:
        return 1;
    }
};


class OrRegex: public Regex {
    SeqRegex a;
public:
    OrRegex(TTokenList& t, size_t& groupCount) : a(t, groupCount) {}

    size_t match_part(const string& str, size_t begin, size_t maxLen, vector<size_t>& groups) override {
        return 1;
    }
};


SeqRegex::SeqRegex(TTokenList& t, size_t& groupCount) {
    if (t.front()->isChar()) {    // Commenting out this portion of code fixes the forever hanging ..
        a = make_unique<Char>(t, groupCount);
    } else {
        cerr << "syntax error, expected [^)]-*^|]" << endl;
        throw SyntaxError();
    }  // ...commenting out up to this point

}

int main() {
    auto tList = tokenize();
    tList.front()->~Token();  //hangs forever if the code 10 lines above is not commented, normally I'll have pop_front() here
    cout << "never gets printed";

    return 0;
}

2 个答案:

答案 0 :(得分:3)

总的来说,可能有十几种独特的场景,使用~T()语法直接调用对象的析构函数是合适的。

这不是这种情况。

如果您打算删除列表中的第一个令牌,只需拨打tList.pop_front()即可。

直接调用析构函数将在以后保留它的std::unique_ptr对象尝试再次删除时调用未定义的行为。因此,当编译/执行此代码时,您无法保证会发生什么或不会发生。

答案 1 :(得分:1)

您有两个名为Char的课程。它们没有相同的定义。这违反了单定义规则(ODR),因而违反了未定义的行为。

我只是好奇为什么当你把文件合并在一起时你没有立即发现这个。