永远悬挂的灾难

Forever hanging destructor

本文关键字:永远      更新时间:2023-10-16

不过,评论一些从未执行的函数定义的行都可以修复它。怎么来?

完整的最小示例我在下面删除无关代码时结束了。

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/anonymon/3b8fa11e90c617b35623ba54320505432050c3e#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;
}

总体上,也许有十几个唯一的方案,可以使用~T()语法直接调用对象的破坏者。

这不是这样的情况。

如果您的目的是删除列表中的第一个令牌,则只需调用tList.pop_front()就足够了。

std::unique_ptr对象稍后将其再次删除它时,直接调用驱动器即将调用不确定的行为。因此,当该代码被编译/执行时,您无法保证会发生什么或不会发生的事情。

您有两个称为Char的类。他们没有相同的定义。这违反了一个定义规则(ODR),因此违反了行为。

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