C++ ArrayStack Push操作空间错误排查与修复求助
Let's break down the problems in your code and fix them one by one. You're right to suspect issues in both the push logic and destructor—there are several key bugs causing the out-of-space errors and potential crashes.
1. Critical Indexing & Capacity Check Bug in push()
Your current push() has two major issues:
- You increment
lengthbefore checking capacity, which means whenlengthequalsmaxCapacity, you immediately trigger an overflow before expanding. - When copying elements during expansion, you loop up to the new
maxCapacity, but your originaltabonly has the oldmaxCapacityelements. This leads to accessing out-of-bounds memory (undefined behavior). - You're storing the new element at
tab[length], but arrays are 0-indexed—since you just incrementedlength, this points to a position beyond the last valid index (e.g., first push:length=1, you use index 1 instead of 0).
2. Destructor Wild Pointer Deletion
Your destructor loops through all maxCapacity elements and deletes them, but only the first length elements were actually allocated with new int(). The rest are uninitialized wild pointers—deleting these will cause crashes or memory corruption.
3. Incorrect Memory Deletion During Expansion
When replacing the old tab, you use delete tab; instead of delete[] tab;—since tab was allocated with new int*[], you must use array deletion to avoid memory leaks.
Fixed Code
ArrayStack.cpp
#include "ArrayStack.h" ArrayStack::ArrayStack() { maxCapacity = DEFAULT_CAPACITY; this->tab = new int* [DEFAULT_CAPACITY]; this->topElement = 0; this->length = 0; // Initialize all pointers to null to avoid wild pointers in destructor for (int i = 0; i < maxCapacity; i++) { tab[i] = nullptr; } } ArrayStack::~ArrayStack() { // Only delete elements that were actually allocated for (int i = 0; i < length; i++) { if (tab[i] != nullptr) { delete tab[i]; } } delete[] tab; // Use array deletion for tab } void ArrayStack::push(int element) { // Check capacity BEFORE incrementing length if (this->length >= this->maxCapacity) { maxCapacity += DEFAULT_CAPACITY; int** temp = new int* [maxCapacity]; // Copy existing elements for (int i = 0; i < this->length; i++) { temp[i] = tab[i]; } // Initialize new empty slots to null for (int i = this->length; i < maxCapacity; i++) { temp[i] = nullptr; } delete[] tab; // Fix: use delete[] for array this->tab = temp; } // Store element at the correct 0-indexed position this->tab[this->length] = new int(element); this->topElement = element; this->length++; // Increment length AFTER storing the element } void ArrayStack::pop() { if (isEmpty()) { throw Empty_Stack(); } delete tab[this->length - 1]; // Fix: use length-1 for 0-index tab[this->length - 1] = nullptr; // Nullify to avoid dangling pointers this->length--; if (isEmpty()) { this->topElement = -1; } else { this->topElement = *tab[this->length - 1]; // Fix: correct index } } int ArrayStack::top() const { if (isEmpty()) { throw Empty_Stack(); } return this->topElement; } bool ArrayStack::isEmpty() const { return this->length == 0; } int ArrayStack::size() const { return this->length; }
Key Fixes Explained
- Capacity Check: Now we check if
length >= maxCapacitybefore adding the element, and expand only once per push (no need for awhileloop—addingDEFAULT_CAPACITYeach time is sufficient). - Indexing: All array accesses now use 0-indexed positions (e.g., we store the element at
tab[length]before incrementinglength, then updatelengthafterward). - Destructor Safety: We only delete the first
lengthelements (the ones we actually allocated), and initialize all unused slots tonullptrto avoid deleting wild pointers. - Memory Deletion: Fixed
delete tab;todelete[] tab;for proper array allocation cleanup. - Pop Fix: Corrected the index when deleting the top element and updating
topElementto match 0-indexed storage.
内容的提问来源于stack exchange,提问作者Nicolas Pellerin

