2010-09-01 69 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 &