为什么我在使用 valgrind 时会出现内存错误? (C++,抽象语法树求值)
Why am I getting memory errors with valgrind? (C++, abstract syntax tree evaluation)
我目前正在为我正在学习的课程做作业。我有一个似乎可以正常工作的程序(我得到了所有测试数据的正确输出),但是当我使用 valgrind 运行 时,它说我有内存错误。这是重现错误的最少代码(仍然很抱歉):
注意:这个作业是关于评估抽象语法树(不是解析,只是评估)
头文件:(由我的导师提供 - 我无法更改)
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*)" 上写着 "Conditional jump or move depends on uninitialised values" .... 通过一些其他不是我的东西... 通过 Let::eval(env*) ... 这是我的。
如果程序存在内存错误,我将获得 0 分。
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;
};
// ...
struct env* newEnv = (struct env*)malloc(sizeof(struct env));
您正在分配 env
,一个使用 C++ 类 的结构,即 std::string
,使用 C 库的 malloc()
,它对 C++ 完全一无所知 类.
这是未定义的行为。 C++ 类 必须用 new
和 delete
分配和销毁。令人惊讶的是,您的代码从一开始就存在足够长的时间来产生任何结果,而不是崩溃和燃烧。
你应该使用 C++ 内存分配:例如
int Let::eval(env *env) {
//make a new struct env to be pushed to the environment stack
env* newEnv = new env();
//copy data into new env struct
newEnv->var = this->bvar;
...
int valToReturn = this->body->eval(newEnv);
delete newEnv;
return valToReturn;
}
此外,在构造函数中初始化数据也是一种很好的做法。至少:
struct env {
env() : next(0) {}
//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;
};
我目前正在为我正在学习的课程做作业。我有一个似乎可以正常工作的程序(我得到了所有测试数据的正确输出),但是当我使用 valgrind 运行 时,它说我有内存错误。这是重现错误的最少代码(仍然很抱歉):
注意:这个作业是关于评估抽象语法树(不是解析,只是评估)
头文件:(由我的导师提供 - 我无法更改)
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*)" 上写着 "Conditional jump or move depends on uninitialised values" .... 通过一些其他不是我的东西... 通过 Let::eval(env*) ... 这是我的。
如果程序存在内存错误,我将获得 0 分。
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;
};
// ...
struct env* newEnv = (struct env*)malloc(sizeof(struct env));
您正在分配 env
,一个使用 C++ 类 的结构,即 std::string
,使用 C 库的 malloc()
,它对 C++ 完全一无所知 类.
这是未定义的行为。 C++ 类 必须用 new
和 delete
分配和销毁。令人惊讶的是,您的代码从一开始就存在足够长的时间来产生任何结果,而不是崩溃和燃烧。
你应该使用 C++ 内存分配:例如
int Let::eval(env *env) {
//make a new struct env to be pushed to the environment stack
env* newEnv = new env();
//copy data into new env struct
newEnv->var = this->bvar;
...
int valToReturn = this->body->eval(newEnv);
delete newEnv;
return valToReturn;
}
此外,在构造函数中初始化数据也是一种很好的做法。至少:
struct env {
env() : next(0) {}
//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;
};