【问题标题】:Exception thrown at 0x003165F0 in tStack.exe: 0xC0000005: Access violation reading location 0x9BFF07EF.?在 tStack.exe 中的 0x003165F0 处引发异常:0xC0000005:访问冲突读取位置 0x9BFF07EF。?
【发布时间】:2016-07-14 09:27:24
【问题描述】:

在 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;


};

我发现一些帖子建议不要使用 using namespace std,但这似乎没有帮助。我只是完全误解了链表的工作原理吗?

【问题讨论】:

  • 您的指针数学在某处不正确。您需要调试您的程序以找出位置。
  • 谢谢,你能帮我清理一下吗?当我说 front->next = temp_ptr;我的想法是否正确,这意味着 front 的 next 指针值现在指向 temp_ptr 指向的位置?
  • 看来其他人已经发现了问题。但是,如果您遇到访问冲突错误,这通常意味着您计算的地址错误,或者您的内存管理不善。还有很抱歉,我已经很久没有处理指针了,我不想让你误入歧途。

标签: c++ list stack


【解决方案1】:

乍一看您的代码,我发现了一个错误。

front = tmp_ptr;
free(tmp_ptr);

这段代码没有意义。您实际上释放了用作堆栈顶部的内存。修复这类错误应该很容易。

【讨论】:

  • 非常感谢。你是指free方法还是front = tmp_ptr;也一样?
  • @Perkis 只免费,你应该记住旧的前线并释放它
【解决方案2】:

通过查看您的代码,我假设您正在尝试以“堆栈”方式实现您的自制链表(先打开,后关闭,反之亦然);如果我错了,请告诉我。

我可以看到您的代码存在一些问题:

问题 1:在您的“Pop”方法中您尝试使用“front”成员,但没有确保在方法第一次运行时它为 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”类定义一个默认构造函数,以便它自动将它的“next”成员分配给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”的“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)
{
}

【讨论】:

  • 哇。谢谢!你回答了我的问题,然后是一些!
  • 就构造函数和析构函数而言,我仍在学习。您是否知道任何可以帮助我为链表编写适当的构造函数和析构函数的资源?我现在似乎有很多泄漏。另外,你知道我怎样才能让 b+ 被视为与 ab+ 一样吗?
  • “资源”是指专门用于链接列表的资源,还是仅用于一般构造函数/析构函数的资源?告诉我,你对构造函数/析构函数了解多少?您是自己将默认构造函数放在代码中,还是从其他人那里复制粘贴?我只问,因为我可以给你一个构造函数和析构函数,只需要几行代码就可以工作,但我想确保你理解我告诉你的内容。你能详细说明你的第二个问题吗?我不完全确定你的意思。 :\
  • 附言。我不知道你是否使用了我的“推送”方法版本,但如果你这样做了,我会稍微改变一下。我注意到我犯了一个小错误。
  • 我通过在标头中创建模板并让 c++ 在 .cpp 文件中进行定义来获得构造函数。我猜我可以使用任何一个。
猜你喜欢
  • 2016-08-17
  • 2021-07-03
  • 1970-01-01
  • 1970-01-01
  • 2021-02-14
  • 2018-12-05
  • 2014-10-26
  • 2013-04-05
  • 1970-01-01
相关资源
最近更新 更多