关于c ++:内存分配/解除分配?

Memory Allocation/Deallocation?

我最近一直在研究内存分配,我对基础知识有点困惑。我还没能把我的头脑集中在简单的事情上。分配内存意味着什么?发生什么事了?我很高兴回答这些问题:

  • 分配的"内存"在哪里?
  • 这是什么"记忆"?数组中的空间?或者别的什么?
  • 当分配这个"内存"时会发生什么?
  • 当内存被释放时会发生什么?
  • 如果有人能回答McLoc在这些C++行中所做的事情,它也会帮助我:

    1
    2
    char* x;
    x = (char*) malloc (8);
  • 谢谢您。


    记忆模型

    C++标准有一个内存模型。它试图以通用的方式对计算机系统中的内存进行建模。标准规定,字节是内存模型中的存储单元,内存由字节组成(§1.7):好的。

    The fundamental storage unit in the C++ memory model is the byte. [...] The memory available to a C++ program consists of one or more sequences of contiguous bytes.

    Ok.

    对象模型

    标准总是提供一个对象模型。这指定对象是存储区域(因此它由字节组成并驻留在内存中)(§1.8):好的。

    The constructs in a C++ program create, destroy, refer to, access, and manipulate objects. An object is a region of storage.

    Ok.

    我们开始吧。内存是存储对象的地方。要将对象存储在内存中,必须分配所需的存储区域。好的。分配和解除分配功能

    该标准提供了两个隐式声明的全局范围分配函数:好的。

    1
    2
    void* operator new(std::size_t);
    void* operator new[](std::size_t);

    如何实施这些不是标准关注的问题。重要的是,它们应该返回一个指向某个存储区域的指针,该存储区域的字节数与传递的参数相对应(§3.7.4.1):好的。

    The allocation function attempts to allocate the requested amount of storage. If it is successful, it shall return the address of the start of a block of storage whose length in bytes shall be at least as large as the requested size. There are no constraints on the contents of the allocated storage on return from the allocation function.

    Ok.

    它还定义了两个相应的释放函数:好的。

    1
    2
    void operator delete(void*);
    void operator delete[](void*);

    定义为释放先前分配的存储(§3.7.4.2):好的。

    If the argument given to a deallocation function in the standard library is a pointer that is not the null pointer value (4.10), the deallocation function shall deallocate the storage referenced by the pointer, rendering invalid all pointers referring to any part of the deallocated storage.

    Ok.

    newdelete

    通常,您不需要直接使用分配和解除分配函数,因为它们只提供未初始化的内存。相反,在C++中,您应该使用EDCOX1 0和EDCOX1 1来动态分配对象。一个新的表达式通过使用上面的分配函数之一来获取所请求类型的存储,然后以某种方式初始化该对象。例如,new int()将为int对象分配空间,然后将其初始化为0。参见5.3.4:好的。< Buff行情>

    新表达式通过调用分配函数(3.7.4.1)来获取对象的存储。好的。

    […]好的。

    创建t类型的对象的新表达式初始化该对象[…]好的。< /块引用>

    在相反的方向,delete将调用对象的析构函数(如果有),然后释放存储(§5.3.5):好的。

    If the value of the operand of the delete-expression is not a null pointer value, the delete-expression will invoke the destructor (if any) for the object or the elements of the array being deleted.

    Ok.

    [...]

    Ok.

    If the value of the operand of the delete-expression is not a null pointer value, the delete-expression will call a deallocation function (3.7.4.2).

    Ok.

    其他分配

    但是,这些并不是分配或释放存储的唯一方法。语言的许多构造隐式地要求分配存储空间。例如,给出一个对象定义,如int a;,还需要存储(§7):好的。

    A definition causes the appropriate amount of storage to be reserved and any appropriate initialization (8.5) to be done.

    Ok.

    C标准库:mallocfree

    此外,头还引入了stdlib.hc标准库的内容,其中包括mallocfree功能。它们也被C标准定义为分配和释放内存,就像C++标准定义的分配和解除分配函数一样。以下是malloc的定义(c99§7.20.3.3):好的。

    void *malloc(size_t size);
    Description
    The malloc function allocates space for an object whose size is specified by size and
    whose value is indeterminate.
    Returns
    The malloc function returns either a null pointer or a pointer to the allocated space.

    Ok.

    以及free的定义(c99§7.20.3.2):好的。

    void free(void *ptr);
    Description
    The free function causes the space pointed to by ptr to be deallocated, that is, made
    available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to free or realloc,
    the behavior is undefined.

    Ok.

    但是,在C++中使用EDCOX1 2和EDOCX1 3的借口是不好的。如前所述,C++有自己的选择。好的。问题的答案

    所以直接回答你的问题:好的。

  • 分配的"内存"在哪里?好的。

    C++标准不关心。它只是说程序有一些由字节组成的内存。可以分配这个内存。好的。

  • 这是什么"记忆"?数组中的空间?或者别的什么?好的。

    只要是有关的标准,只是在内存是一个字节序列。这是一个非常通用的标准purposefully,只tries典型的计算机系统模型。你可以认为,在大部分的模型,它在你的计算机的RAM中。

  • 这是什么时候发生的"记忆"有分配吗?

    分配的内存区储存,使一些可用于使用的程序。initialized对象是在分配内存。所有你需要知道的是,你可以分配的内存。目前你的物理内存分配的过程往往是由操作系统完成。

  • 是什么发生当内存有deallocated吗?

    这导致一些以前deallocating分配存储器存储器是不可用的程序。它成为deallocated存储。

  • 它还将帮助我,如果有人真的是不可能在这些数的答案:C + +线

    1
    2
    char* x;
    x = (char*) malloc (8);

    在这里,我们malloc是一个8字节的内存分配。它返回的指针被浇到一char*x和存储过程。

  • 好的。


    1)正在分配的"内存"在哪里?

    这完全不同于您的操作系统、编程环境(GCC vs Visual C++ + Vorland C++与其他任何东西)、计算机、可用内存等。一般来说,内存是从被称为堆的内存区分配的,内存区只是在等待着您使用。它通常使用您可用的RAM。但总有例外。在大多数情况下,只要它能给我们记忆,它从哪里来就不是一个大问题。有一些特殊类型的内存,例如虚拟内存,它们可能在任何给定的时间实际在RAM中,也可能在实际内存不足时移动到硬盘(或类似的存储设备)。一个完整的解释会很长时间!

    2)这是什么"记忆"?数组中的空间?或者别的什么?

    内存通常是计算机中的RAM。如果把内存想象成一个巨大的"数组"是有帮助的,那么它一定像一个数组一样工作,然后把它想象成一吨字节(8位值,很像unsigned char值)。它从内存底部的索引0开始。不过,和以前一样,这里也有大量的异常,内存的某些部分可能被映射到硬件上,或者根本不存在!

    3)当分配这个"内存"时会发生什么?

    在任何时候都应该有(我们真的希望!)其中一些可供软件分配。它的分配方式高度依赖于系统。通常,分配内存的一个区域,分配器将其标记为已用,然后给您一个指针,指示程序内存在系统的所有内存中的位置。在您的示例中,程序将找到一个8字节(char)的连续块,并返回一个指针,指向将该块标记为"正在使用"后找到该块的位置。

    4)当内存被释放时会发生什么?

    系统将该内存标记为可再次使用。这是非常复杂的,因为这通常会导致内存漏洞。分配8个字节,再多分配8个字节,然后释放前8个字节,就有了一个漏洞。有整本书都写在处理释放、内存分配等方面,所以希望简短的回答就足够了!

    5)如果有人能回答这些C++语言中的Maloc所做的事情,它也会帮助我:

    非常粗略,假设它在一个函数中(顺便说一句,永远不要这样做,因为它不会释放内存并导致内存泄漏):

    1
    2
    3
    4
    void mysample() {
      char *x; // 1
      x = (char *) malloc(8); // 2
    }

    1)这是本地堆栈空间中保留的指针。它还没有初始化,所以它指向内存中的任何部分。

    2)调用参数为8的malloc。Cube只是让C/C++知道你想要它是一个(char *),因为它返回了一个(空洞*),这意味着它没有应用类型。然后结果指针存储在X变量中。

    在非常粗糙的x86 32位程序集中,这看起来有点像

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    PROC mysample:
      ; char *x;
      x = DWord Ptr [ebp - 4]
      enter 4, 0   ; Enter and preserve 4 bytes for use with

      ; x = (char *) malloc(8);
      push 8       ; We're using 8 for Malloc
      call malloc  ; Call malloc to do it'
    s thing
      sub esp, 4   ; Correct the stack
      mov x, eax   ; Store the return value, which is in EAX, into x

      leave
      ret

    第3点对实际分配进行了模糊描述。malloc通常只是为此调用一个系统函数来处理其余的一切,和这里的其他功能一样,它在操作系统到操作系统、系统到系统等方面有很大的不同。


    1 . Where is the"memory" that is being allocated?

    从语言的角度来看,这并没有具体说明,主要是因为细节的细节通常并不重要。此外,C++标准往往会在指定硬件细节方面出错,以最小化不必要的限制(编译器可以在平台上运行,也可以在可能的优化上运行)。

    Sftrabbit的答案非常全面地介绍了这一点(这是您真正需要的),但我可以给出一些有用的例子。

    例1:

    在一台足够旧的单用户计算机(或足够小的嵌入式计算机)上,大多数物理RAM可以直接用于您的程序。在这种情况下,调用mallocnew本质上是内部簿记,允许运行库跟踪当前使用的RAM块。你可以手动完成,但很快就会变得单调乏味。

    例2:

    在现代多任务操作系统中,物理RAM与许多进程和其他任务(包括内核线程)共享。它还用于后台的磁盘缓存和I/O缓冲,并由虚拟内存子系统进行扩充,虚拟内存子系统可以在不使用数据时将数据交换到磁盘(或其他存储设备)。

    在这种情况下,调用new可以首先检查进程内部是否有足够的空闲空间,如果没有,可以向操作系统请求更多的空间。返回的内存可能是物理内存,也可能是虚拟内存(在这种情况下,在实际访问之前,物理RAM可能不会分配给存储它)。您甚至无法分辨这两者之间的区别,至少在没有使用特定于平台的API的情况下是如此,因为内存硬件和内核合谋将其隐藏起来。

    2 . What is this"memory"? Space in an array? Or something else?

    在示例1中,它类似于数组中的空间:返回的地址标识物理RAM的可寻址块。即使在这里,RAM地址也不一定是扁平的或连续的——有些地址可能是为ROM或I/O端口保留的。

    在示例2中,它是指向更虚拟的内容的索引:进程的地址空间。这是一个抽象,用于隐藏进程中的底层虚拟内存细节。当您访问这个地址时,内存硬件可能直接访问一些实际的RAM,或者它可能需要请求虚拟内存子系统提供一些。

    3 . What happens exactly when this"memory" gets allocated?

    通常,会返回一个指针,您可以使用该指针存储所需的任意多个字节。在这两种情况下,mallocnew操作员将进行一些内务处理,以跟踪进程地址空间的哪些部分被使用,哪些是空闲的。

    4 . What happens exactly when the memory gets deallocated?

    一般来说,freedelete会做一些内务处理,这样他们就知道内存可以重新分配。

    It would also really help me if someone could answer what malloc does in these C++ lines:

    1
    2
    char* x;
    x = (char*) malloc (8);

    它返回一个指针,该指针可以是NULL(如果找不到所需的8个字节),也可以是一些非空值。

    对于这个非空值,您唯一能有用地说的是:

    • 访问这8个字节中的每一个都是合法的(也是安全的)x[0]..x[7]
    • 访问x[-1]x[8]或实际上任何x[i]是非法的(未定义的行为),除非0 <= i <= 7是非法的。
    • 比较任何一个x, x+1, ..., x+8都是合法的(尽管你不能取消最后一个的引用)。
    • 如果您的平台/硬件/任何东西对在内存中存储数据的位置有任何限制,那么x满足这些限制。


    分配内存意味着向操作系统请求内存。这意味着程序本身只在需要时才要求RAM中有"空间"。例如,如果您想使用一个数组,但在程序运行之前不知道它的大小,您可以做两件事:-声明并用您指定的x数组[x],任意长。例如100。但是,如果您的程序只需要一个由20个元素组成的数组呢?你在白白浪费记忆。-然后,当程序知道x的正确大小时,就可以对x元素数组进行malloc。内存中的程序分为4段:-堆栈(调用函数时需要)-代码(bibary可执行代码)-数据(全局变量/数据)-堆,在这个段中找到分配的内存。当你决定不再需要分配的内存时,你就把它还给操作系统。

    如果要分配和数组10个整数,请执行以下操作:

    int*数组=(int*)malloc(sizeof(int)*10)

    然后你把它还给操作系统自由(数组)