这个简单的堆栈实现有什么问题

时间:2011-05-14 14:49:50

标签: c++

看看这个天真(并且仅用于培训目的)堆栈的实现

#ifndef _STACK_H_
#define _STACK_H_
#include <algorithm>

template <typename T>
class Stack
{
    private:
        T* data_;
        size_t size_;
        size_t allocated_;
    public:
        Stack() : data_(new T[10]),size_(0),allocated_(10) {}
        ~Stack() 
        { 
            delete[] data_; 
        }
        size_t size() const { return size_; }
        T top() const
        {
            if (size_ == 0)
                throw "Error the Stack is Empty";
            return data_[size_]; 
        }

        void pop() 
        { 
            if (size_ == 0) 
                throw "Error the Stack is Empty";
            else
                --size_;
        }

        void push(T toAdd)
        {
            if (size_ < allocated_)
                data_[++size_] = toAdd;
            else
            {
                T* newData = new T[allocated_*2];
                std::copy(data_,data_ + size_,newData);
                delete[] data_;
                data_ = newData;
                ++size_;
                allocated_ = allocated_*2;
            }
        }

        size_t capacity() const { return allocated_; }
};

#endif

然后如果我在我的测试应用程序中使用它:

#include <iostream>
#include "Stack.h"
using std::endl;
using std::cout;

int main(int argc,char* argv[])
{
    Stack<int> myStack;

    cout << myStack.size() << " it should be 0" << endl;
    cout << myStack.capacity() << " it should be 10" << endl;
    try 
    {
        cout << myStack.top() << " it should be 40" << endl;
    }
    catch(...)
    {
        cout << "Error the stack is empty" << endl;
    }

    myStack.push(10);
    myStack.push(20);
    myStack.push(30);
    myStack.push(40);

    cout << myStack.size() << " it should be 4" << endl;
    cout << myStack.capacity() << " it should be 10" << endl;
    cout << myStack.top() << " it should be 40" << endl;
    myStack.push(50);
    myStack.push(60);
    myStack.push(70);
    myStack.push(80);
    myStack.push(90);
    myStack.push(100);
    myStack.push(110);
    myStack.push(120);

    cout << myStack.size() << " it should be 12" << endl;
    cout << myStack.capacity() << " it should be 20" << endl;
    cout << myStack.top() << " it should be 120" << endl;

    myStack.push(50);
    myStack.push(60);
    myStack.push(70);
    myStack.push(80);
    myStack.push(90);
    myStack.push(100);
    myStack.push(110);
    myStack.push(120);
    myStack.push(210);
    myStack.push(220);

    cout << myStack.size() << " it should be 22" << endl;
    cout << myStack.capacity() << " it should be 40" << endl;
    cout << myStack.top() << " it should be 220" << endl;

    myStack.pop();
    myStack.pop();
    myStack.pop();
    myStack.pop();
    myStack.pop();
    myStack.pop();
    myStack.pop();
    myStack.pop();
    myStack.pop();
    myStack.pop();  
    myStack.pop();
    myStack.pop();
    myStack.pop();

    cout << myStack.size() << " it should be 9" << endl;
    cout << myStack.capacity() << " it should be 20" << endl;
    cout << myStack.top() << " it should be 90" << endl;

    myStack.pop();
    myStack.pop();
    myStack.pop();
    myStack.pop();
    myStack.pop();
    myStack.pop();
    myStack.pop();
    myStack.pop();
    myStack.pop();

    cout << myStack.size() << " it should be 0" << endl;
    cout << myStack.capacity() << " it should be 40" << endl;

    try 
    {
        myStack.top();
    }
    catch(...)
    {
        cout << "Error the stack is empty" << endl;
    }

    try 
    {
        myStack.pop();
    }
    catch(...)
    {
        cout << "Error the stack is empty" << endl;
    }

    return 0;
}

我收到了这个错误:

0 it should be 0
10 it should be 10
Error the stack is empty
4 it should be 4
10 it should be 10
40 it should be 40
12 it should be 12
20 it should be 20
120 it should be 120
22 it should be 22
40 it should be 40
220 it should be 220
9 it should be 9
40 it should be 20
90 it should be 90
0 it should be 0
40 it should be 40
*** glibc detected *** /home/alessandro/Projects/testStack/testStack/bin/Debug/testStack: malloc(): memory corruption (fast): 0x0000000000871040 ***
======= Backtrace: =========
/lib/libc.so.6(+0x775b6)[0x7f6c49c395b6]
/lib/libc.so.6(+0x7b8e9)[0x7f6c49c3d8e9]
/lib/libc.so.6(__libc_malloc+0x6e)[0x7f6c49c3e58e]
/usr/lib/libstdc++.so.6(__cxa_allocate_exception+0x17)[0x7f6c4a4a87d7]
/home/alessandro/Projects/testStack/testStack/bin/Debug/testStack[0x401471]
/home/alessandro/Projects/testStack/testStack/bin/Debug/testStack[0x4012ac]
/lib/libc.so.6(__libc_start_main+0xfd)[0x7f6c49be0c4d]
/home/alessandro/Projects/testStack/testStack/bin/Debug/testStack[0x400ba9]
======= Memory map: ========
00400000-00402000 r-xp 00000000 08:05 13107397                           /home/alessandro/Projects/testStack/testStack/bin/Debug/testStack
00601000-00602000 r--p 00001000 08:05 13107397                           /home/alessandro/Projects/testStack/testStack/bin/Debug/testStack
00602000-00603000 rw-p 00002000 08:05 13107397                           /home/alessandro/Projects/testStack/testStack/bin/Debug/testStack
00871000-00892000 rw-p 00000000 00:00 0                                  [heap]
7f6c44000000-7f6c44021000 rw-p 00000000 00:00 0 
7f6c44021000-7f6c48000000 ---p 00000000 00:00 0 
7f6c49bc2000-7f6c49d3c000 r-xp 00000000 08:05 13500726                   /lib/libc-2.11.1.so
7f6c49d3c000-7f6c49f3b000 ---p 0017a000 08:05 13500726                   /lib/libc-2.11.1.so
7f6c49f3b000-7f6c49f3f000 r--p 00179000 08:05 13500726                   /lib/libc-2.11.1.so
7f6c49f3f000-7f6c49f40000 rw-p 0017d000 08:05 13500726                   /lib/libc-2.11.1.so
7f6c49f40000-7f6c49f45000 rw-p 00000000 00:00 0 
7f6c49f45000-7f6c49f5b000 r-xp 00000000 08:05 13500495                   /lib/libgcc_s.so.1
7f6c49f5b000-7f6c4a15a000 ---p 00016000 08:05 13500495                   /lib/libgcc_s.so.1
7f6c4a15a000-7f6c4a15b000 r--p 00015000 08:05 13500495                   /lib/libgcc_s.so.1
7f6c4a15b000-7f6c4a15c000 rw-p 00016000 08:05 13500495                   /lib/libgcc_s.so.1
7f6c4a15c000-7f6c4a1de000 r-xp 00000000 08:05 13500730                   /lib/libm-2.11.1.so
7f6c4a1de000-7f6c4a3dd000 ---p 00082000 08:05 13500730                   /lib/libm-2.11.1.so
7f6c4a3dd000-7f6c4a3de000 r--p 00081000 08:05 13500730                   /lib/libm-2.11.1.so
7f6c4a3de000-7f6c4a3df000 rw-p 00082000 08:05 13500730                   /lib/libm-2.11.1.so
7f6c4a3df000-7f6c4a4d5000 r-xp 00000000 08:05 9834159                    /usr/lib/libstdc++.so.6.0.13
7f6c4a4d5000-7f6c4a6d5000 ---p 000f6000 08:05 9834159                    /usr/lib/libstdc++.so.6.0.13
7f6c4a6d5000-7f6c4a6dc000 r--p 000f6000 08:05 9834159                    /usr/lib/libstdc++.so.6.0.13
7f6c4a6dc000-7f6c4a6de000 rw-p 000fd000 08:05 9834159                    /usr/lib/libstdc++.so.6.0.13
7f6c4a6de000-7f6c4a6f3000 rw-p 00000000 00:00 0 
7f6c4a6f3000-7f6c4a713000 r-xp 00000000 08:05 13500723                   /lib/ld-2.11.1.so
7f6c4a8e5000-7f6c4a8e9000 rw-p 00000000 00:00 0 
7f6c4a90f000-7f6c4a912000 rw-p 00000000 00:00 0 
7f6c4a912000-7f6c4a913000 r--p 0001f000 08:05 13500723                   /lib/ld-2.11.1.so
7f6c4a913000-7f6c4a914000 rw-p 00020000 08:05 13500723                   /lib/ld-2.11.1.so
7f6c4a914000-7f6c4a915000 rw-p 00000000 00:00 0 
7fffdbc1e000-7fffdbc33000 rw-p 00000000 00:00 0                          [stack]
7fffdbc7b000-7fffdbc7c000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
The application was terminated by a signal: SIGABRT

奇怪的是,如果我用Stack<int>Stack<double>替换Stack<char>,错误就会消失! 我正在使用g ++(Ubuntu 4.4.3-4ubuntu5)4.4.3。

我无法发现Stack中的错误,您有什么想法吗?

2 个答案:

答案 0 :(得分:3)

问题出在push。它应该是:

if (size_ < allocated_)
    data_[size_++] = toAdd;
//            ^^^^^^^

此外,top应该返回data_[size_-1]


解释 - 第一个修复 - 在开头,size_==0,当你执行data_[++size_]时,你直接写第二个元素,索引为1(不是前缀 { {1}})。

第二个修复 - 类似错误 - 所有索引从0开始到n,不包含。所以你的范围是[0,n),这就是你应该返回索引为operator++

的元素的原因

编辑:唉,对,您错过了在size_-1成员函数的else中添加新元素。

答案 1 :(得分:1)

在你的Top函数中,它应该是return data_ [size_ - 1];

push函数似乎也错了,当你重新分配你的缓冲区时,你不会写入值来推入它。