我目前正在为我正在做的课程做一个任务。我有什么似乎是一个完整的工作程序(我得到正确的输出所有我的测试数据),但是当我用valgrind运行它说我有内存错误。下面是最少的代码重现错误(这仍然是颇有几分不好意思):为什么我会用valgrind得到内存错误? (C++,抽象语法树评估)
注:此分配有关评估抽象语法树(不解析,只是评估)
头文件:(提供我的导师 - 我不能改变这一点)
struct env {
//will be used to store the values of variables in a stack. This is one 'node' of the stack
string var;
int value;
env *next;
};
class Exp {
//general expression - eval will be overridden.
public:
virtual int eval(env*) = 0;
};
class Constant : public Exp {
int n;
public:
Constant(int n) {this->n = n; }
int eval(env*);
};
class Var : public Exp {
string name;
public:
Var(string s) { this->name = s; }
int eval(env*);
};
class Let : public Exp {
//let binding. (let bvar = bexp in body)
//used to assign a value to variables
string bvar;
Exp *bexp;
Exp *body;
public:
Let(string v, Exp *e, Exp *b)
{
bvar = v; bexp = e; body = b;
}
int eval(env*);
};
这是我写的,以评估语法的这个子集的代码:当我运行日
#include <string>
using namespace std;
#include "evalobj2.h"
int Constant::eval(env *env) {
return this->n;
}
int Var::eval(env *env) {
while(env) {
if ((env->var).compare(this->name) == 0) return env->value;
env = env->next;
}
//give up - variable not found in env
throw 1;
}
int Let::eval(env *env) {
//make a new struct env to be pushed to the environment stack
struct env* newEnv = (struct env*)malloc(sizeof(struct env));
//copy data into new env struct
newEnv->var = this->bvar;
newEnv->value = this->bexp->eval(env);
//make it the head of the "environment" so that it is seen first when looking up a value
newEnv->next = env;
//evaluate
int valToReturn = this->body->eval(newEnv);
free(newEnv);
return valToReturn;
}
从一个主要的方法,我从valgrind得到“6错误的6个错误”:
Exp *e = new Let("x",new Constant(1),new Var("x"));
cout << e2->eval(nullptr) << endl;
即使我得到正确的结果。我已经对更大的数据结构进行了测试,其余的语法都需要进行评估,所有这些都给出了正确的结果。
我不明白Valgrind在抱怨什么!它说“有条件的跳转或移动取决于未初始化的值”在“operator delete(void *)”....通过其他一些不是我的东西...通过Let :: eval(env *)... which是我的。
对于有内存错误的程序,我将得到0分。
除了使用'malloc'而不是'new []','Exp'类需要一个虚拟析构函数。如果您尝试使用Exp * e = new Let(...)... delete e;''释放内存,则行为未定义。 – PaulMcKenzie
*头文件:(由我的导师提供 - 我不能改变这个)* - 你的导师需要一个导师。如果您应该使用基类指针动态地创建从'Exp'派生的对象,并且(如应该要求的那样)解除分配内存,那么您的导师的头文件存在严重问题,因为如果不引入未定义的行为就无法完成,更可能的是,未定义的行为是内存泄漏。原因在我上面的第一条评论中提到。你的导师的等级为'F'。 – PaulMcKenzie