我目前正在出于教学目的创建玩具语言,并且最近检查了我的代码是否存在内存泄漏;但是,在Visual Studio中,我的代码中的随机位置似乎存在内存泄漏,这些内存泄漏不会使用“ new”在堆上分配任何内容。不仅如此,它还说我在调试打印要删除的内存位置丢失了60个字节。
我的语言是用抽象语法树设置的,该树概括了某些表达式和语句。在这些语句的每一个中,都有一个destroy方法,该方法删除我拥有的所有其他Ast指针,并删除其任何子级。此方法消除并删除所有多余的指针。但是,在随机位置有随机内存泄漏,因为我确认已删除的一个或两个指针没有释放它们的内存。目前,我尝试将使用“ new”关键字分配的所有指针分配到一个指针数组中,并尝试释放所有指针,但是最终比我的原始清理方法泄漏更多。
这是当前的解析方法
void Parser::parse(VirtualMachine& vm) {
while (curr().getType() != EOF_Token) {
Ast* ast = parseStatement(vm, true);
ast->parse();
ast->destroy(); // This is the cleanup method
vm.compile();
std::cout << "DELETING: " << ast << std::endl;
delete ast;
}
vm.clear();
}
主要方法如下:
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
try {
auto t1 = std::chrono::high_resolution_clock::now();
ace::Parser parser(file, lines);
parser.parse(parser.vm);
auto t2 = std::chrono::high_resolution_clock::now();
std::cout << "took "
<< std::chrono::duration_cast<std::chrono::milliseconds>(t2
t1).count()
<< "ms\n";
}
catch(std::exception&) {
return EXIT_FAILURE;
}
destroy方法的示例如下所示(BinaryAst):
void destroy() override {
// Destroying other object's children if they are also a BinaryAst
left->destroy();
right->destroy();
// Debug Print
std::cout << "DELETING: " << left << std::endl;
std::cout << "DELETING: " << right << std::endl;
// Deleting the current ast's children
delete left;
delete right; // This one is deleted but still has the memory leak
left = nullptr;
right = nullptr;
}
这是解析语句方法。它将隐式返回该结构的子级。
Ast* Parser::parseStatement(VirtualMachine& vm, bool flag) {
if (curr().getType() == EOF_Token)
return nullptr;
else if (curr().getToken() == "var" || curr().getToken() == "let")
return parseVariableAssignment(vm);
else if (curr().getType() == LCurlyBrace)
return parseBlock(vm, flag);
else if (curr().getToken() == "print")
return parsePrintStatement(vm);
else if (curr().getToken() == "input")
return parseInputStatement(vm);
else if (curr().getType() != EOF_Token && peek(1).getToken() == "=")
return parseVariableReassignment(vm);
else if (curr().getToken() == "if")
return parseIfStatement(vm, false);
else if (curr().getToken() == "while")
return parseWhileStatement(vm);
else {
auto expression = parseExpression(vm);
if (expression == nullptr) {
auto current = curr();
Error::unexpectedToken(current, lines[curr().getLine() - 1]);
}
return expression;
}
return nullptr;
}
我在这里设置了调试标志,以告诉我任何错误。对于内存泄漏,我得到的输出如下:
Detected memory leaks!
Dumping objects ->
// Al the other 8 bytes point to the same random location which does not provide any allocation for pointers
{2855} normal block at 0x01326FC8, 8 bytes long.
Data: < H2 > 98 48 32 01 00 00 00 00
// This is the block of memory that I have freed but shows as leaking
{2854} normal block at 0x01324880, 60 bytes long.
Data: <`(* Q2 <$* > 60 28 2A 00 C8 51 32 01 3C 24 2A 00 05 00 00 00
{2211} normal block at 0x01325DB0, 8 bytes long.
Data: < [1 > 80 5B 31 01 00 00 00 00
{1747} normal block at 0x01326088, 8 bytes long.
Data: < R2 > 90 52 32 01 00 00 00 00
{1476} normal block at 0x01326F20, 8 bytes long.
Data: <$R2 > 24 52 32 01 00 00 00 00
{1167} normal block at 0x01326E78, 8 bytes long.
Data: < H2 > 98 48 32 01 00 00 00 00
{823} normal block at 0x013274D0, 8 bytes long.
Data: < [1 > 80 5B 31 01 00 00 00 00
Object dump complete.
所有其他块似乎都指向我的头文件中某些变量的声明的末尾,这些变量都没有使用new或指针进行分配。试图弄清内存泄漏是什么还是有点误导。
我期望输出是没有内存泄漏。我以为输出至少会显示没有泄漏的字节数,除了它向没有任何内存分配的位置显示的随机泄漏之外。