开发者

What's wrong with this simple stack implementation

take a look at this naive (and just for training purpose) implementation of stack

#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

Then If I use it in my test application:

#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);
开发者_StackOverflow中文版    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;
}

I got this error:

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

The weird thing is that if I replace Stack<int> with Stack<double> or Stack<char> the error disappear! I am using g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3.

I cannot spot the error in Stack,do you have any ideas?


The problem is in your push. It should be:

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

Also, top should return data_[size_-1]


Explanation - the first fix - at the beginning, size_==0 and when you do data_[++size_] you write directly at the second element, with index 1 (not the prefix operator++ ).

The second fix - similar error - all indexes start from 0 to n, non-inclusive. So your range is [0, n), that's why you should return the element with index, size_-1

EDIT : Argh, right, you're missing to add the new element in the else of your push member function.


In your Top function, it should be return data_[size_ - 1];

The push function seems wrong too, when you reallocate your buffer, you don't write the value to push in it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜