代码之家  ›  专栏  ›  技术社区  ›  Satbir

C++中的删除和新建

c++
  •  6
  • Satbir  · 技术社区  · 15 年前

    这可能是一个很简单的问题,但请帮助我。

    我想知道当我调用new&delete时会发生什么,例如下面的代码

    char * ptr=new char [10];
    
    delete [] ptr;
    

    调用new返回内存地址。它是否在堆上精确分配10个字节,在堆中存储有关大小的信息。当我对同一指针调用delete时,我在调试器中看到在10个字节之前和之后有很多字节发生了更改。

    每个新文件是否有包含新文件分配的字节数信息的标题?

    谢谢

    8 回复  |  直到 15 年前
        1
  •  13
  •   Johann Gerell    15 年前

    它能精确分配10个字节吗

    这取决于实现。担保是“ 至少 10个字符。

    在哪里存储有关大小的信息?

    这取决于实现。

    每个新文件是否有包含新文件分配的字节数信息的标题?

    这取决于实现。

    “这取决于实现”,我的意思是标准中没有定义。

        2
  •  5
  •   sth    15 年前

    这完全取决于编译器和运行时库。它只是精确定义了什么影响 new delete 在你的程序上有,但是这些是如何准确地被接受并没有被指定。

    在您的情况下,似乎分配的内存比请求的内存多一点,它可能会存储管理信息,如当前内存块的大小、有关相邻可用空间区域的信息或帮助调试器尝试检测缓冲区溢出和类似问题的信息。

        3
  •  3
  •   sharptooth    15 年前

    它完全依赖于实现。一般情况下,您必须在其他地方存储元素的数量。实现必须为至少指定的元素数分配足够的空间,但它可以分配更多的空间。

        4
  •  3
  •   sepp2k    15 年前

    每个新文件是否有包含新文件分配的字节数信息的标题?

    这取决于平台,但是的,在许多平台上都有。

        5
  •  2
  •   jweyrich    15 年前

    准确地说,根据标准, new char[10] 意志分配 至少 堆中有10个字节。

    的内部 new delete 依赖于实现。因此,它将因编译器而异,也因平台而异。此外,您还可以找到各种分配器算法(例如: TCMalloc )

    我会给你一个大概的介绍 能够 内部工作,但不要把它当作绝对真理。它是专门为这个解释而写的。

    简而言之, 新的 运算符内部调用 malloc . 这个 马洛克 使用一个很长的可用内存块链接列表 free chain . 什么时候? 马洛克 调用时,它会查找这个列表中第一个足够大的块来容纳请求的大小。在那之后,它将块分成两部分,一部分按您请求的大小,另一部分按剩余部分,然后将其添加回自由链。最后,它返回请求大小的块。

    反向发生在 free 调用,由delete/delete[]调用。简而言之,它将提供的块放回 自由链 .

    在我上面描述的过程中,可能会有一些花哨的技巧,比如对 自由链 ,将请求的大小四舍五入到下一个二次方,以减少内存碎片,等等。

        6
  •  0
  •   Vijay    15 年前
    char * ptr=new char [10];
    

    您正在堆中创建一个10个字符的数组,并将第0个元素的地址存储在指针中。这类似于在C中执行malloc操作。

    delete [] ptr;
    

    您正在删除(释放内存)先前语句分配的堆内存。这类似于在C中执行释放操作。

        7
  •  0
  •   sep    15 年前

    它依赖于实现,但内存块的元数据通常存储在返回内存地址之前的区域中。在10个字节之前观察到的更改可能是为此块更新的元数据(可能是块的大小写入元数据),在10个字节之后是为下一个块更新的元数据(仍然未分配,可能是指向空闲列表中下一个块的指针)。

    处理堆不是一个好主意,因为它不可移植。但是,如果您想实现这种堆魔法,我建议您实现自己的内存池(只需从堆中获取一大块内存并自己管理)。一个可能的出发点是 libmm .

        8
  •  0
  •   camh    15 年前

    尽管具体情况取决于实现,但实现需要存储的一条信息是数组中元素的数量。或者,如果它不直接存储它,它将需要从分配的块大小中准确地派生它。

    原因是,如果用new[]分配对象数组,则当用delete[]删除对象时,需要调用数组中每个对象的析构函数。delete[]需要知道要销毁多少对象。这就是为什么需要将new与delete匹配,将new[]与delete[]匹配。