为什么我不能通过指针从数组中删除非第一个元素

Why can't I delete other-than-first element from array by pointer

考虑以下代码:

int main()
{
  int *intArPtr = new int[100];
  int *intArPtr1 = intArPtr + 1;

  delete [] intArPtr; //ok
  //delete intArPtr; //valgrind warning, but no leaks!
  //delete intArPtr1; //invalid pointer error

  return 0;
}

我知道 delete [] intArPtr 是删除此数组的唯一有效方法,但我只是对以下内容感到好奇:

  1. 为什么 delete intArPtr 没有产生任何内存泄漏?是吗 未定义的行为,我很幸运没有任何行为?
  2. 为什么 delete intArPtr1 在 运行 时出错?为什么它不删除所有元素而是首先从数组中删除?
  3. C++ 的 运行time 如何知道分配数组的大小(对于 delete [])?它存储在某个地方吗?
  1. Why delete intArPtr doesn't yield any memory leaks? Is it undefined behavior and I'm just lucky no to have any?

正确,在分配给 new[] 的内存上调用 delete 是未定义的行为。一方面,它不会调用数组成员的析构函数。

对于两个,即使您只是询问内存释放而不是对象销毁,deletedelete[] 的实现可能相同,也可能不同。他们读起来好像他们是同一件事,但他们不是:deletedelete[] 是两个不同的运算符,可能具有不同的实现。他们可以使用不同的分配策略(请参阅下面问题 #3 的答案)。

  1. Why delete intArPtr1 gives an error on run-time? Why doesn't it delete all elements but first from the array?

你必须传递 delete 分配给 new 的指针。确切的指针。不是 new 分配的内存区域中的指针,这是行不通的。它必须是指向区域开始的相同指针。

  1. How does C++'s runtime knows size of the allocated array (for delete [])? Is it stored somewhere?

一个常见的分配器策略是在分配区域之前存储分配的字节数。 delete 然后会获取您传递给它的指针,向左看 4 或 8 个字节,并将该整数解释为该区域的大小。如果您向它传递一个指向其他地方的指针,它的回溯策略将会失败。

C++ 语言没有指定如何跟踪内存分配,因此这是一个实现细节。不同的标准库、编译器和操作系统会以不同的方式执行此操作。我所描述的只是一种可能的机制。

延伸阅读:

答案:

  1. 您的示例中没有内存泄漏。事实上,如果数组中的对象自己分配了一些内存并且应该在析构函数中释放该内存,则删除不带 [] 的数组只会导致内存泄漏。在所有其他情况下,不正确的删除不会导致内存泄漏。
  2. 因为分配的内存大小就存储在指针之前。当您访问数组中除第一个元素以外的任何其他元素时,那里没有合适的内存大小。
  3. 见 2.
  1. 为什么删除 intArPtr 不会产生任何内存泄漏?这是未定义的行为吗,我很幸运没有?

同时是和否。使用 delete 而不是 delete[] 并不干净,但通常有效。基本上指针和偏移量都在分配时存储。这允许在使用 delete 时进行正确的重新分配,即使是偶然的。

  1. 为什么删除 intArPtr1 会在 运行 时出错?为什么它不删除所有元素而是首先从数组中删除?

intArPtr1不对应分配区域的指针。当试图delete那个的时候,运行的时候在分配table.

的时候找不到这个地址
  1. C++ 的 运行time 如何知道分配数组的大小(对于 delete [])?它存储在某个地方吗?

它存储在分配table中,并带有指向分配区域的指针。