为什么我不能通过指针

时间:2015-09-30 21:28:06

标签: c++ arrays memory-management memory-leaks 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;
}

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

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

3 个答案:

答案 0 :(得分:12)

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

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

对于两个人来说,即使您只是询问内存释放而不是关于对象破坏,deletedelete[]也可以相同地实现,或者它们可以不同。他们读起来就像他们一样,但他们不是:deletedelete[]是两个不同的运算符,可能有不同的实现。他们可以使用不同的分配策略(参见下面问题#3的答案)。

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

您必须传递delete分配有new的指针。确切的指针。不是new分配的内存区域内的指针,它不起作用。它必须是指向该区域起点的相同指针。

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

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

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

进一步阅读:

答案 1 :(得分:0)

  1. 为什么删除intArPtr不会产生任何内存泄漏?它是不确定的行为,我很幸运没有任何?
  2. 是和否同时。使用delete代替delete[]并不干净,但通常有效。基本上,指针和偏移量都在分配时存储。这允许在使用delete时进行适当的释放,即使偶然也是如此。

    1. 为什么删除intArPtr1会在运行时出错?为什么它不删除所有元素,而是首先从数组中删除?
    2. intArPtr1与分配区域的指针不对应。尝试delete时,运行时无法在分配表中找到此地址。

      1. C ++的运行时如何知道已分配数组的大小(对于delete [])?它存放在某个地方吗?
      2. 它存储在分配表中,指针指向已分配的区域。

答案 2 :(得分:-2)

数目:

  1. 你的例子中没有内存泄漏。事实上,如果数组中的对象有自己分配的内存并且应该在析构函数中释放该内存,则删除不带[]的数组只会导致内存泄漏。在所有其他情况下,不正确的删除不会导致内存泄漏。
  2. 因为分配的内存大小就存储在指针之前。当您访问数组的任何其他元素但第一个元素时,那里没有适当的内存大小。
  3. 见2.