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

rsh*_*sht 4 c++ arrays memory-leaks memory-management heap-memory

考虑以下代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

  1. 为什么delete intArPtr不产生任何内存泄漏?是不确定的行为,我很幸运没有任何?
  2. 为什么delete intArPtr1在运行时出错?为什么不首先从数组中删除所有元素?
  3. C++的运行时如何知道已分配数组的大小(对于delete [])?它存放在某个地方吗?

Joh*_*ica 12

  1. 为什么delete intArPtr不产生任何内存泄漏?是不确定的行为,我很幸运没有任何?

正确,调用delete分配的内存是未定义的行为new[].首先,它不会调用数组成员上的析构函数.

对于二,即使你只是询问内存释放,而不是关于对象的破坏,这是可能的delete,并delete[]要实现相同的,或者它们是不同的.他们读起来就像他们是同一个东西,但他们不是:delete并且delete[]是两个不同的运营商,可能有不同的实现.他们可以使用不同的分配策略(参见下面问题#3的答案).

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

你必须传递delete一个分配的指针new.确切的指针.不是new指定内存区域内的指针,不起作用.它必须是指向该区域起点的相同指针.

  1. C++的运行时如何知道已分配数组的大小(对于delete [])?它存放在某个地方吗?

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

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

进一步阅读: