类析构函数处的堆损坏

Heap Corruption at class destructor?

本文关键字:损坏 析构函数      更新时间:2023-10-16

我已经想了好几个小时了,我已经无计可施了。如果有人能告诉我什么时候我做错了,我一定会很感激的。

我写了一个c++代码,类实现了一个简单的堆栈,试图推送和弹出随机的字符流。它似乎工作得很好,但在文件的末尾,它会产生某种运行时错误:

HEAP CORRUPTION DETECTED: after Normal block....

由于错误发生在文件的末尾,我猜测删除指针(类析构函数)时存在问题。然而,我不知道我写的析构函数出了什么问题。

此外,经过一番尝试和错误之后,我发现如果我将较大的数字寻址到无符号整数值iter1(例如:80),则不会发生运行时错误。你能解释一下这里的问题是什么,以及如何绕过它吗?

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();
}

ssackBuffer[++ssackIndex]=c;

当堆栈只剩下一个元素时,将写入ssackBuffer的末尾。

如果你考虑一个1号的堆栈。在第一次呼叫中,推送该线路将评估为:

sstackBuffer[1] = c;

这超出了你分配的内存。

请确保您了解增量前运算符和增量后运算符之间的区别。通过您的代码示例,我建议您在推送中使用后增量,在弹出中使用前增量。