Search code examples
c++classpointersheap-corruption

Heap Corruption at class destructor?


I've been trying to figure this out for hours now, and I'm at my wit's end. I would surely appreciate it if someone could tell me when I'm doing wrong.

I wrote a c++ code with class implementing a simple stack, trying to push and pop random stream of characters. It seems to work fine, but at the end of the file, it produces some sort of runtime error:

HEAP CORRUPTION DETECTED: after Normal block....

Since the error occurs at the end of the file, my guess is that there is a problem at deleting the pointer(class destructor). However, I have no idea what is wrong with the destructor I wrote.

Also, after some trial and error, I found out that if I address a bigger number to unsigned integer value iter1 (ex: 80), the runtime error does not occur. Could you explain what is the problem here, and how to bypass it?

stack.h:

class sstack
{
public:
    sstack(int length = 256);
    ~sstack(void);
    int sstackPop(char &c);
    int sstackPush(char c);
    bool isempty();
    bool isFull();

protected:
private:
    char *sstackBuffer;
    int sstackSize;
    int sstackIndex; // Initial = -1
};

stack.cpp:

#include "stack.h"
#include <iostream>
using namespace std;

sstack::sstack(int length)
{
    sstackIndex = -1;
    if (length > 0)
        sstackSize = length;
    else
        sstackSize = 256;

    sstackBuffer = new char[sstackSize];
}

sstack::~sstack(void)
{
    delete[] sstackBuffer;
}

bool sstack::isempty()
{
    if (sstackIndex < 0)
    {
        cout << "is empty!(isempty)" << endl;
        return 1;
    }
    else
        return 0;
}

bool sstack::isFull()
{
    if (sstackIndex >= sstackSize)
        return 1;
    else
        return 0;
}


int sstack::sstackPop(char &c)
{
    if (!isempty())
    {
        c = sstackBuffer[sstackIndex--];
        cout << sstackIndex << endl;
        return 1;
    }
    else
    {
        cout << "is empty!(sstackPop)" << endl;
        return 0;
    }       
}

int sstack::sstackPush(char c)
{
    if (!isFull())
    {
        sstackBuffer[++sstackIndex] = c;
        return 1;
    }
    else{
        return 0;
    }

}

main.cpp:

#include <iostream>
#include "stack.h"
#include <string>
using namespace std;

int main(){
    unsigned int iter1 = 5;
    unsigned int iter2 = 800;

    sstack stackDefault;
    sstack stack1(iter1);
    sstack stack2(iter2);

    char buffer[80];
    memset(buffer, 0x00, 80);
    char BUFFER[80] = "A random stream of characters";
    strcpy_s(buffer, 80, BUFFER);

    for (int i = 0; i< strlen(buffer); i++)
    {
        cout << " stack1: " << stack1.sstackPush(buffer[i]);
        cout << " stack2: " << stack2.sstackPush(buffer[i]);
        cout << " stackD: " << stackDefault.sstackPush(buffer[i]);
        cout << " i : "<< i << endl;
    }

    cout << "out of Pushes" << endl;

    int i = 0;
    memset(buffer, 0x00, 80);
    while (!stack1.isempty())
        stack1.sstackPop(buffer[i++]);

    cout << buffer << endl;
    getchar();

}

Solution

  • sstackBuffer[++sstackIndex] = c;

    Will write past the end of sstackBuffer when the stack only has one element left.

    If you consider a stack of size 1. In the first call to push that line would evaluate to:

    sstackBuffer[1] = c;

    Which is beyond the memory you've allocated.

    Be sure you're aware of the difference between pre-increment and post-increment operators. By your code example I would suggest you use post-increment in push and pre-increment in pop.