2010-09-01 66 views
0

这是我第一次尝试C++。我在C++中做了一个基于数组的堆栈,并且析构函数抛出了一些内存转储。我无法弄清楚哪里出了问题。基于数组的堆栈 - 析构函数中的错误



#include <stdio.h> 
#include <iostream> 
#include <exception> 

using namespace std; 

class FullStackException : public exception { 
    virtual const char* what() const throw() { 
     return "Stack is full."; 
    } 
} fsex; 

class EmptyStackException : public exception { 
    virtual const char* what() const throw() { 
     return "Stack is empty."; 
    } 
} esex; 

template <class D> 
class ArrayBasedStack { 
private: 
    int t; //t represents top 
    D *S; 
    int arrSize; 
public: 
    ArrayBasedStack(int arraySize = 10); 
    ~ArrayBasedStack(); 
    int size(); /*returns the number of elements stored*/ 
    void push(D&); /*inserts an element*/ 
    D pop(); /*removes and returns the last inserted element*/ 
    D top(); /*returns the last inserted element without removing it*/ 
    int isEmpty(); /*indicates whether no elements are stored*/ 
}; 

template <class D> 
ArrayBasedStack<D>::ArrayBasedStack(int arraySize) { 
    /* Elements are added from left to right */ 
    S = new D[arraySize]; 
    arrSize = arraySize; 
    /* t keeps track of the index of the top element */ 
    t = -1; 
} 

template <class D> 
ArrayBasedStack<D>::~ArrayBasedStack() { 
    if(S != NULL) { 
     int i = 0; 
     for(i = 0; i < size(); i++) { 
      S[i] = NULL; 
     } 
     cout << "about to delete S" << endl; 
     delete[] S; 
    } 
} 

template <class D> 
int ArrayBasedStack<D>::size() { 
    return t; 
} 

template <class D> 
void ArrayBasedStack<D>::push(D& data) { 
    if(t == arrSize) { 
     throw fsex; 
    } else { 
     S[t] = data; 
     t++; 
    } 
} 

template <class D> 
D ArrayBasedStack<D>::pop() { 
    if(isEmpty()) { 
     throw esex; 
    } 
    D element = S[t]; 
    S[t--] = NULL; 
    return element; 
} 

/* 
* returns true if the stack is empty, false otherwise 
*/ 
template <class D> 
int ArrayBasedStack<D>::isEmpty() { 
    return (t < 0); 
} 

int main(int argc, char *argv[]) { 

    char inputs[][10] = { 
     "str1" 
    }; 

    char *i = NULL; 

    ArrayBasedStack<char *> stack; 
    i = inputs[0]; 
    stack.push(i); 
    try { 
     stack.pop(); 
    } 
    catch(exception& ex) { 
     cout << "ERR:" << ex.what() << endl; 
    } 
    return 0; 
} 

 
+0

不知道这是怎么可怜一个典型的例子。这比我学习C++时要好得多。 :) – Mike 2010-09-01 02:06:27

+1

做得很好。顺便说一句 - 在析构函数和pop()中使用S [i] = NULL,但是这并没有做任何特别有用的事情(对于D = char *,这意味着打印出整个堆栈可能允许重复检查如果你不推送(NULL)),但它确实意味着你实例化的任何类型D必须从NULL分配,这是一个相当大的和不必要的限制。在C++中,不需要x = NULL作为垃圾收集器的提示。你也可以安全地删除NULL,所以析构函数可以简单地删除[] S,但是你很谨慎。 – 2010-09-01 02:41:08

回答

2

问题行是

t = -1; 

应该

t = 0; 

,因为当您添加第一个元素,下面的代码是excecuted

} else { 
     S[t] = data; // t == -1 
     t++; 
    } 
+0

+1,打我。最佳做法是始终避免使用无效索引。 – Potatoswatter 2010-09-01 02:11:03

+0

代码需要更多的更改,而不仅仅是一项分配。有些部分是基于假设t是顶级的假设,有些假设是顶级的假设。 – 2010-09-01 02:42:55

0

以下是罪魁祸首。

template <class D> 
void ArrayBasedStack<D>::push(D& data) { 
    if(t == arrSize) { 
     throw fsex; 
    } else { 
     S[t] = data;  // Should be S[++t] = data; 
     t++;    // Comment out this line 
    } 
} 

这implemntation假设“T”指向堆栈上的最顶层元素,而不是用于push

注意,操作符[]和操作者具有++相同的优先级的下一个可用位置。由于它们从左到右关联,因此在operator ++之前评估[]。

在你的实现中,这是问题所在。当t被初始化为-1时,覆盖超出S [-1]处的数组下标,这导致undefined behavior

至少在我的系统上,当试图释放堆栈类的析构函数中的内存时会出现问题。这是一个syptom可见经过多次混日子行动发生

还建议push采取参数D const &