注释掉一些从未执行过的函数定义,但修复了它。怎么样?
完整的最小示例我最终删除了以下不相关的代码。
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;
}
答案 0 :(得分:3)
总的来说,可能有十几种独特的场景,使用~T()
语法直接调用对象的析构函数是合适的。
这不是这种情况。
如果您打算删除列表中的第一个令牌,只需拨打tList.pop_front()
即可。
直接调用析构函数将在以后保留它的std::unique_ptr
对象尝试再次删除时调用未定义的行为。因此,当编译/执行此代码时,您无法保证会发生什么或不会发生。
答案 1 :(得分:1)
您有两个名为Char
的课程。它们没有相同的定义。这违反了单定义规则(ODR),因而违反了未定义的行为。
我只是好奇为什么当你把文件合并在一起时你没有立即发现这个。