C++中new创建数组的delete[]问题:无原指针与重复释放解析
new[]数组的原指针时如何正确删除数组? 问题背景
当无法直接访问用new[]声明的数组的原指针(已知数组大小)时,该如何正确删除这个数组?以下是示例代码及出现的问题:
void enlarge(int * x) { int * tmp = new int[20]; memcpy(tmp, x, 10*sizeof(int)); delete[] x; //? x = tmp; } int main() { int * x = new int[10]; enlarge(x); delete[] x; //??? free(): double free detected in tcache 2 }
疑问解答
1. enlarge函数内的delete[]是否知晓需释放的内存大小?
是的,delete[]完全清楚要释放的内存大小。C++在通过new[]分配数组内存时,会在内存块的头部(对用户不可见的区域)存储数组的元素数量或总内存大小信息,delete[]执行时会读取这个隐藏信息,从而准确释放整个数组的内存,不需要手动传入大小参数。只要你持有数组的首指针,delete[]就能正确完成释放。
2. main函数内的delete[]触发错误的原因是什么?该如何避免?
错误原因:这是典型的**双重释放(double free)**问题。
enlarge函数的参数x是按值传递的,函数内部对x的修改(x = tmp)只会改变函数内的局部变量,不会影响main函数里的原指针。也就是说,main中的x仍然指向最初用new[10]分配的内存,而这块内存已经在enlarge里被delete[] x释放过一次了,main里再次调用delete[] x就属于重复释放同一块内存,触发内存错误。解决方法:把
enlarge的参数改为指针的引用,这样函数内部对x的修改会同步到main中的原指针。修改后的函数签名为void enlarge(int*& x),这样enlarge里的x = tmp会让main里的x指向新分配的数组,main中的delete[] x就会释放新数组,不会出现重复释放的问题。
修改后的完整代码:
void enlarge(int*& x) { int* tmp = new int[20]; memcpy(tmp, x, 10 * sizeof(int)); delete[] x; x = tmp; } int main() { int* x = new int[10]; enlarge(x); delete[] x; // 正常释放,无错误 }
额外说明:如果真的遇到原指针丢失的情况(比如没有保存指针副本),那只能确保在指针丢失前已经用delete[]释放内存,否则会造成内存泄漏。你的示例问题本质是参数传递方式错误,并非真正无法访问原指针。
内容的提问来源于stack exchange,提问作者user1079505

