tStack.exe中的0x003165F0抛出异常:0xC0000005:访问冲突读取位置0x9BFF07EF。?
我似乎无法确定这个计划的问题。我不断在不同的地方得到像这样的读/写错误。这是.cpp和.h
的.cpp:
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
#include <string>
#include <iostream>
//using namespace std;
tStack::tStack()
{
}
tStack::~tStack()
{
}
tStack::tStack(const tStack &)
{
}
void tStack::Pop()
{
snode *tmp_ptr = NULL;
if (front)
{
tmp_ptr->next = front;
front = tmp_ptr;
free(tmp_ptr);
}
else
std::cout << "\nStack is Empty";
}
void tStack::Push(std::string op)
{
snode *tmp_ptr = front;
tmp_ptr->data = op;
if (front)
{
tmp_ptr->next = front;
front = tmp_ptr;
}
else
{
front = tmp_ptr;
front->next = NULL;
}
}
void tStack::Print()
{
snode *cur_ptr = front;
if (cur_ptr)
{
std::cout << "\nElements in Stack:\n";
while (cur_ptr)
{
std::cout << cur_ptr->data;
cur_ptr = cur_ptr->next;
}
std::cout << "\n";
}
else
std::cout << "\nStack is Empty";
}
void tStack::cStack()
{
free(front);
}
void tStack::convert(std::string postfix, tStack a)
{
int count = 0;
bool lastOper;
std::string pusher, val1, val2;
for (int i = 0; i < postfix.size(); i++)
{
if (isalpha(postfix[i]))
{
pusher = postfix[i];
a.Push(pusher);
count++;
}
else
{
if (count < 2)
{
std::cout << "There are not enough values to perform an operation.";
}
else
{
pusher = postfix[i];
val1 = front->data;
a.Pop();
val2 = front->data;
a.Pop();
a.Push(")");
a.Push(val1);
a.Push(pusher);
a.Push(val2);
a.Push("(");
}
lastOper = true;
}
}
}
·H:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
#include <string.h>
#include <iostream>
//using namespace std;
class snode
{
public:
std::string data;
snode *next;
};
class tStack
{
public:
tStack();
~tStack();
tStack(const tStack &);
void Pop();
void Push(std::string);
void Print();
void cStack();
void convert(std::string, tStack);
private:
snode *front;
};
我发现一些帖子暗示不使用命名空间std,但似乎没有帮助。我是否完全误解了链接列表的工作原理?
答案 0 :(得分:0)
首先看一下您的代码,我发现了一个错误。
front = tmp_ptr;
free(tmp_ptr);
这段代码毫无意义。你实际上释放了用作堆栈顶部的内存。修复这些错误应该很容易。
答案 1 :(得分:0)
通过查看您的代码,我会假设您尝试以“堆栈”方式实现自制链表(首先,最后关闭,反之亦然);如果我错了,请告诉我。
我可以看到您的代码存在一些问题:
问题1 :在你的“Pop”方法中你试图使用“前”成员而不确保当方法第一次运行时它是NULL;在“tStack”的默认构造函数中为它添加一个定义,将其赋值为NULL。
问题2 :我相信您希望“Pop”方法从列表中删除元素,而不是添加它们。我对么?如果是这样,那么你的“Pop”方法实现不正确。以下是“Pop”方法的正确编写版本:
void tStack::Pop()
{
if (front)
{
snode *tmp_ptr = front;
front = front->next;
free(tmp_ptr);
}
else
std::cout << "\nStack is Empty";
}
注意:我以一种将列表视为“堆栈”的方式实现了此方法。
此代码提出了另一个重要主题,您应该为“snode”类定义一个默认构造函数,以便它自动将其“下一个”成员分配给NULL。
问题3:您的“推送”方法未正确实施。 “tmp_ptr”应分配给 new 内存,而不是列表的第一个元素。
该行:
snode *tmp_ptr = front;
应该是:
snode *tmp_ptr = new snode;
注意:您可以通过以下方式缩短“推送”方法:
void tStack::Push(std::string op)
{
snode *tmp_ptr = new snode;
tmp_ptr->data = op;
tmp_ptr->next = front;
front = tmp_ptr;
}
注意:此代码假定如果没有后续元素,“snode”s“next”成员将始终等于NULL。这是为您的“snode”类实现自定义默认构造函数对您有好处的一个原因。
问题4:“cStack”方法应遍历列表中的每个元素并单独释放每个元素。您现在拥有的当前实现只释放第一个元素。
建议:任何包含指向它拥有的动态分配内存的指针的类都可以使用自定义析构函数来清除它已分配的动态内存。即使使用方法从外部源清除动态内存,这也适用,因为备份计划总是好的。
但是,这个建议不适用于你的“snode”类(至少不适用于它的“下一个”成员),因为“删除”你的一个列表的元素会导致它设置一个连锁反应会删除所有以下要素
嗯,这就是我能看到的所有问题。如果我的回复有帮助,请告诉我。 :)
编辑:您的“tStack”类有一个空白的默认构造函数:
tStack::tStack()
{
}
将其更改为:
tStack::tStack()
: front(NULL)
{
}
您的默认析构函数是:
tStack::~tStack()
{
}
将其更改为:
tStack::~tStack()
{
// Clear the dynamic memory if needed.
if (front)
cStack();
}
最后,在“snode”类中添加一个默认构造函数:
snode::snode()
: next(NULL)
{
}