分配新堆栈时编程错误

时间:2012-08-22 10:13:03

标签: c++ stack

我正在编写一个程序来实现一个像真实世界堆栈一样工作的堆栈,这意味着它在堆栈大小达到阈值时会倒塌,因此需要创建一个新堆栈来插入新元素。

以下是我的计划:

#include <iostream>
#include<vector>
#include<stack>

using namespace std;

class stack_of_plates
{
   vector<stack<int> > stacks;
   unsigned int stack_size;
   public:
   stack_of_plates(unsigned int size=100)
   {
       stack_size=size;
   }

   void push(int data)
   {
       if(stacks.empty())
       {
           stack<int> *sptr= new stack<int>; //on debugging Segmentation fault at thisline
           stacks.push_back(*sptr);
       }

       vector<stack<int> >::iterator it=stacks.end();
       if(it->size()==stack_size)
       {
           stack<int> *sptr= new stack<int>; //on debugging Segmentation fault at thisline
           stacks.push_back(*sptr);
       }
       it->push(data);
   }

   void pop()
   {
       if(stacks.empty())
       {
           cout<<"\nEmpty Stack";
           return ;
       }
       vector<stack<int> >::iterator it=stacks.end();
       if(it->empty())
       {
           it--;
       }
       it->pop();
   }
   int top()
   {
       if(stacks.empty())
       {
           cout<<"\nEmpty Stack";
           return 0;
       }
       vector<stack<int> >::iterator it=stacks.end();
       if(it->empty())
       {
           it--;
       }
       return it->top();
   }
};


int main()
{
   stack_of_plates ss;
   ss.push(1);
   ss.push(2);
   cout<<ss.top();
   return 0;
}

编译时不会出现错误或警告。但程序终止时会出现异常错误。 在调试其给出分段错误错误时指示分配新堆栈的问题。 请帮助我如何在分配新堆栈时更改我的代码。请帮我删除此错误。

3 个答案:

答案 0 :(得分:3)

stacks.end();是指向量结束后的(不存在的)元素。你不能取消引用它;这样做会导致未定义的行为,可能是分段错误。

你在那里做什么并不是很清楚,但是如果你想要最后一个元素的迭代器,那么要么减少它:

vector<stack<int> >::iterator it=stacks.end();  // points past the end
--it;                                           // points to last element

或使用反向迭代器(在这种情况下,使用++而不是--向后移动序列):

vector<stack<int> >::reverse_iterator it=stacks.rbegin();

向向量添加元素可能会使其无效,因此it->push_back(data)末尾的push()不正确。你可以避免在这里使用迭代器:

void push() {
    if (stacks.empty() || stacks.back().size()==stack_size) {
        // See below for explanation of this change
        stacks.push_back(stack<int>());
    }
    stacks.back().push(data);
}

pop()中,你可能想删除最后一个堆栈,如果它是空的;否则,你最终会得到两个空堆栈,而你的代码将错误地尝试其中一个pop。同样,这样做可能会导致分段错误或其他未定义的行为。你可能想要这样的东西:

void pop() {
    if (stacks.empty()) {
        cout<<"\nEmpty Stack";
        return ;
    }
    stacks.back().pop();
    if (stacks.back().empty()) {
        stacks.pop_back();
    }
}

现在我们已经建立了一个不变量,即最后一个堆栈永远不会为空,top可以更简单一些:

int top() {
    if (stacks.empty()) {
        cout<<"\nEmpty Stack";
        return 0;
    }
    return stacks.back().top();
}

此外,您通常不希望使用new创建对象,尤其是在这样的情况下,您将对象的副本放入向量,然后丢弃指针,泄漏分配的内存。您可以向向量添加一个空堆栈,如下所示:

stacks.push_back(stack<int>());

有时(但不是在这种情况下)您可能希望存储指向容器中已分配对象的指针;在这种情况下,要么记得在从容器中删除它们时删除它们,要么存储智能指针,例如std::unique_ptr。但在这种情况下,只需存储对象。

答案 1 :(得分:1)

代码存在许多问题,因此很难说哪一个是导致问题的直接原因。您需要逐个清理它们然后重新测试。如果您仍有问题,请在此处发布新代码。

以下是清单:

  1. 您的分配中存在内存泄漏问题。由于你有一个堆栈向量,你需要做的就是调整向量的大小,并分配一个新的堆栈。所以

    stacks.resize(stacks.size() + 1);

    而不是

    stack<int> *sptr= new stack<int>; stacks.push_back(*sptr);

  2. vector&lt;&gt; .end()返回一个指向最后一个元素的迭代器,这就是为什么@Joachim建议你在使用它之前需要递减迭代器的原因。

    < / LI>
  3. 检查是否将存储转移到新堆栈时出现逻辑错误 - 检查最后一个堆栈的大小是否为最大值,然后创建新堆栈,继续推送旧堆栈。

  4. 我希望这会有所帮助。

答案 2 :(得分:0)

std::stack<int>已经具有您在示例中显示的功能,因此不需要std::vector< std::stack<int> >。只需按下并弹出std::stack<int>即可避免代码中出现的大部分问题。没有理由将std::stack<int>限制为stack_size

接下来,当您需要容器中的最后一个条目时,请使用back()代替end()