为什么删除分配的数组会导致内存错误?
Why does deleting an allocated array cause a memory error?
出于教育目的,我实现了一个 ArrayList class,但在我的 expand() 方法中删除数组时,我 运行 遇到了内存错误。
这是我的 class 和所有重要的方法:
//create array with default size 2
template<class T>
ArrayList<T>::ArrayList(){
realSize = 2;
count = 0;
data = new T[realSize];
}
//destructor
template<class T>
ArrayList<T>::~ArrayList() {
delete []data;
}
//adds value to end of list
template<class T>
void ArrayList<T>::add(T val) {
//if reached end of array, expand array
if (count >= realSize)
expand();
data[count] = val;
count++;
}
//inserts value at index
template<class T>
void ArrayList<T>::insert(T val, int index) {
if (!isValid(index)) return;
//if index is greater than current size, expand
while (index >= realSize || count >= realSize) {
expand();
}
//shift values before index
for (int i = count; i >= index; i--) {
T val = data[i];
data[i + 1] = data[i];
}
data[index] = val;
count++;
}
//return value at index
template<class T>
T ArrayList<T>::get(int index) {
if (!isValid(index)) return 0;
return data[index];
}
template<class T>
int ArrayList<T>::size() {
return count;
}
template<class T>
void ArrayList<T>::expand() {
//double array size
realSize = realSize * 2;
T* newData = new T[realSize];
//replace data
for (int i = 0; i < count; i++) {
newData[i] = data[i];
}
delete[]data; //<--ERROR OCCURS HERE
data = newData;
}
这是一些会导致错误的代码
ArrayList<int>* list = new ArrayList<int>();
list->add(1);
list->add(5);
list->insert(2, 1);
list->insert(3, 2);
list->insert(4, 3); //<---ERROR OCCURS HERE
错误是一个消息框,上面写着
Debug Error!
Program:
...ommunity\Common7\IDE\Extensions\TestPlatorm\testhost.x86.exe
HEAP CORRUPTION DETECTED: after Normal block (#296) at 0x05D69BC0
CRT detected that the application wrote to memory after end of heap buffer.
为什么调用expand方法时偶尔会报错?据我所知,当调用 expand() 时,数组处于预期顺序(在我的示例中,它是 {1, 2, 3, 5}
)。
问题出在insert
方法中。当您将现有元素复制到新元素 space 时,您从元素 count
开始,然后将 data[count]
向上复制一个槽位到 data[count + 1]
。但是,没有元素存储在 data[count]
中,在正确的情况下,对 data[count + 1]
的访问将超过分配给 data
.
的 space
那些情况发生在第二次 insert
调用中。 count
是 3,realsize
是 4,index
是 2,所以不会发生扩展。您的 for 循环将分配 data[count + 1] = data[count]
,即 data[4] = data[3]
。由于数据只有 4 个元素的 space,写入 data[4]
会破坏已分配 space 末尾的数据,这在稍后的内存操作中检测到(在这种情况下,当分配的space 通过调用 delete
).
释放
解决方案是在 int i = count - 1
处开始循环,或者在以下条件下递减它:
for (int i = count; --i >= index; )
无关,T val = data[i];
声明没有任何用处,可以删除。
出于教育目的,我实现了一个 ArrayList class,但在我的 expand() 方法中删除数组时,我 运行 遇到了内存错误。
这是我的 class 和所有重要的方法:
//create array with default size 2
template<class T>
ArrayList<T>::ArrayList(){
realSize = 2;
count = 0;
data = new T[realSize];
}
//destructor
template<class T>
ArrayList<T>::~ArrayList() {
delete []data;
}
//adds value to end of list
template<class T>
void ArrayList<T>::add(T val) {
//if reached end of array, expand array
if (count >= realSize)
expand();
data[count] = val;
count++;
}
//inserts value at index
template<class T>
void ArrayList<T>::insert(T val, int index) {
if (!isValid(index)) return;
//if index is greater than current size, expand
while (index >= realSize || count >= realSize) {
expand();
}
//shift values before index
for (int i = count; i >= index; i--) {
T val = data[i];
data[i + 1] = data[i];
}
data[index] = val;
count++;
}
//return value at index
template<class T>
T ArrayList<T>::get(int index) {
if (!isValid(index)) return 0;
return data[index];
}
template<class T>
int ArrayList<T>::size() {
return count;
}
template<class T>
void ArrayList<T>::expand() {
//double array size
realSize = realSize * 2;
T* newData = new T[realSize];
//replace data
for (int i = 0; i < count; i++) {
newData[i] = data[i];
}
delete[]data; //<--ERROR OCCURS HERE
data = newData;
}
这是一些会导致错误的代码
ArrayList<int>* list = new ArrayList<int>();
list->add(1);
list->add(5);
list->insert(2, 1);
list->insert(3, 2);
list->insert(4, 3); //<---ERROR OCCURS HERE
错误是一个消息框,上面写着
Debug Error!
Program: ...ommunity\Common7\IDE\Extensions\TestPlatorm\testhost.x86.exe
HEAP CORRUPTION DETECTED: after Normal block (#296) at 0x05D69BC0
CRT detected that the application wrote to memory after end of heap buffer.
为什么调用expand方法时偶尔会报错?据我所知,当调用 expand() 时,数组处于预期顺序(在我的示例中,它是 {1, 2, 3, 5}
)。
问题出在insert
方法中。当您将现有元素复制到新元素 space 时,您从元素 count
开始,然后将 data[count]
向上复制一个槽位到 data[count + 1]
。但是,没有元素存储在 data[count]
中,在正确的情况下,对 data[count + 1]
的访问将超过分配给 data
.
那些情况发生在第二次 insert
调用中。 count
是 3,realsize
是 4,index
是 2,所以不会发生扩展。您的 for 循环将分配 data[count + 1] = data[count]
,即 data[4] = data[3]
。由于数据只有 4 个元素的 space,写入 data[4]
会破坏已分配 space 末尾的数据,这在稍后的内存操作中检测到(在这种情况下,当分配的space 通过调用 delete
).
解决方案是在 int i = count - 1
处开始循环,或者在以下条件下递减它:
for (int i = count; --i >= index; )
无关,T val = data[i];
声明没有任何用处,可以删除。