如何删除[]衰减的数组?[复制]

How to delete[] decayed array? [duplicate]

提问人:user1079505 提问时间:5/8/2023 最后编辑:Vlad from Moscowuser1079505 更新时间:5/8/2023 访问量:102

问:

如果我无权访问原始指针 x,如何删除声明的数组?假设,我知道数组大小。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. 函数内是否知道要释放多少内存?delete[]enlarge()
  2. 显然,within 会导致在执行过程中出现错误。为什么?如何避免?delete[]main()
C++ 指针 dynamic-memory-allocation delete-operator pass-by-value

评论

1赞 Igor Tandetnik 5/8/2023
enlarge应该返回一个新指针,然后可以调用为 .否则,您将删除旧内存并泄漏新内存。调用方也无法再访问。更好的是,帮自己一个忙并使用x = enlarge(x)std::vector<int>
0赞 fabian 5/8/2023
是的,确实如此。不过,最好将释放数据留给智能指针:void enlarge(std::unique_ptr<int[]> & x) { auto tmp = std::make_unique<int[]>(20); memcpy(tmp.get(), x, 10 * sizeof(int)); x = std::move(tmp); } int main() {auto x = std::make_unique<int[]>(10); enlarge(x);}
3赞 drescherjm 5/8/2023
显然,main() 中的 delete[] 在执行过程中会导致错误。为什么?如何避免?因为你是按值传递的。 复制 x 并放大它,释放原始内存位置,但在 main 中不更改,在运行 en large in 后指向您尝试第二次释放的原始位置xvoid enlarge(int * x) {xxint main()int main()
5赞 Konrad Rudolph 5/8/2023
顺便说一句,阵列衰减的概念在这里无关紧要。无论如何,它不会发生在你的代码中:你声明的指针(而不是数组)类型的所有变量。
1赞 JaMiT 5/8/2023
@user1079505 “你的意思是数组衰减仅指静态声明的数组,例如使用 int x[10]?” -- 不准确。仅当对象类型为数组时,才会发生数组衰减。如果声明,则 的类型为数组。如果声明,则 的类型为指针。指针不能受到从数组到指针的衰减的影响,因为 1) 指针不是数组,并且 2) 指针已经是指针。int x[10]xint * xx

答:

1赞 fireshadow52 5/8/2023 #1

其中的调用正在删除声明的 ,因为您只是将指针传递给新函数。这就是为什么在给你一个双倍免费;该指针不再存在。deleteenlargeint *xmaindelete[] xmain

更新:我应该澄清一下,当你按值传递指针时,你实际上是在复制它。指针的副本也是原始指针。deletedelete

2赞 Vlad from Moscow 5/8/2023 #2

该函数会产生内存泄漏,因为在 main 中声明的指针是按值传递给函数的。也就是说,该函数处理原始指针值的副本。在函数中更改副本时,将保持在 main 中声明的原始指针不变。enlargexxx

因此,这句话在 main

delete[] x;

调用未定义的行为,因为指针指向的内存已在函数中释放。xenlarge

您需要通过引用传递指针,例如

void enlarge(int * &x) {
    int * tmp = new int[20];
    memcpy(tmp, x, 10*sizeof(int));
    delete[] x;
    x = tmp;
}

请注意,最好使用标准容器,而不是原始指针。std::vector

2赞 eerorika 5/8/2023 #3

如果我无法访问原始指针 x,如何删除用 new 声明的数组?

你不能。为了删除动态数组,您必须知道指向该数组的第一个元素的指针,即 返回的指针。new

enlarge() 函数中的 delete[] 会知道要释放多少内存吗?

是的。

显然,main() 中的 delete[] 在执行过程中会导致错误。为什么?

因为相同的指针已经在 中删除了。如果多次删除指针,则程序的行为是未定义的。enlarge

如何避免?

不要多次删除指针。

P.S. 泄漏了它分配的数组。不要使用 new 和 delete。请改用 RAII 容器。enlargestd::vector


啊,所以数组衰减只影响静态声明的数组

数组衰减是将数组类型的表达式隐式转换为指向第一个元素的指针。的类型是 。这不是数组类型。 是指针类型。由于它不是数组类型,因此它不会隐式转换为指向第一个元素的指针。 已经是指向第一个元素的指针。xint*int*x

评论

0赞 user1079505 5/8/2023
啊,所以数组衰减只影响静态声明的数组,而动态声明的数组总是可以用 删除,只要我有一些指向第一个元素的指针?delete[]