我最近一直关注内存分配,而且我对基础知识有点困惑。我无法绕过简单的东西。分配内存意味着什么?怎么了?我很感激这些问题的答案:
如果有人能够回答malloc在这些C ++行中所做的事情,这对我也有帮助:
char* x;
x = (char*) malloc (8);
谢谢。
答案 0 :(得分:11)
1)正在分配的“记忆”在哪里?
这完全不同,基于您的操作系统,编程环境(gcc vs Visual C ++ vs Borland C ++ vs其他任何东西),计算机,可用内存等。一般来说,内存是从所谓的堆,区域分配的。记忆只是等着你使用。它通常会使用您可用的RAM。但总有例外。在大多数情况下,只要它给了我们记忆,它来自哪里并不是一个很大的问题。存在特殊类型的存储器,例如虚拟存储器,其在任何给定时间实际上可能或可能不在RAM中,并且如果用尽实际存储器,则可能移动到硬盘驱动器(或类似的存储设备)。完整的解释会很长!
2)这个“记忆”是什么?阵列中的空间?或其他什么?
内存通常是计算机中的RAM。如果将内存视为一个巨大的“数组”是有帮助的,那么它肯定会像一个一样运行,然后将其视为一吨字节(8位值,非常类似于unsigned char
值)。它从内存底部的索引0开始。就像以前一样,这里有很多例外,内存的某些部分可能映射到硬件,甚至根本不存在!
3)当“内存”被分配时会发生什么?
在任何给定的时间都应该(我们真的希望!)其中一些可供软件分配。如何分配是高度依赖系统的。通常,分配一个内存区域,分配器将其标记为已使用,然后指定给您使用它指示程序在内存所在的所有系统内存中的位置。在您的示例中,程序将找到一个8字节(char)的连续块,并在将其标记为“正在使用”之后返回指向块找到该块的指针。
4)当内存被取消分配时会发生什么?
系统将该内存标记为可再次使用。这非常复杂,因为这通常会在内存中造成漏洞。分配8个字节,然后再分配8个字节,然后解除分配前8个字节,你就有了一个漏洞。有关于处理释放,内存分配等的全书都有。所以希望简短的答案就足够了!
5)如果有人能够回答malloc在这些C ++行中所做的事情,那对我来说也会有所帮助:
非常粗暴,并假设它在一个函数中(顺便说一句,永远不要这样做,因为它不会释放你的内存并导致内存泄漏):
void mysample() {
char *x; // 1
x = (char *) malloc(8); // 2
}
1)这是在本地堆栈空间中保留的指针。它没有被初始化,因此它指向内存中的任何内存。
2)它使用参数8调用malloc。演员只是让C / C ++知道你想要它(char *),因为它返回一个(void *)意味着它没有应用任何类型。然后生成的指针存储在x变量中。
在非常粗糙的x86 32位程序集中,这看起来很模糊
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 :(得分:7)
1。正在分配的“记忆”在哪里?
从语言的角度来看,这没有指定,主要是因为细节通常无关紧要。此外,C++
标准往往错误地指定硬件细节,以最小化不必要的限制(平台编译器可以运行,以及可能的优化)。
sftrabbit的回答很好地概述了这一结果(这是你真正需要的),但我可以提供一些有用的例子,以防万一。
在足够旧的单用户计算机(或足够小的嵌入式计算机)上,大多数物理RAM可能直接可用于您的程序。在这种情况下,调用malloc
或new
本质上是内部簿记,允许运行时库跟踪当前正在使用的RAM的哪些块。您可以手动执行此操作,但很快就会变得乏味。
在现代多任务操作系统上,物理RAM与许多进程和其他任务共享,包括内核线程。它还用于后台的磁盘缓存和I / O缓冲,并由虚拟内存子系统进行扩充,该子系统可以在不使用时将数据交换到磁盘(或其他存储设备)。
在这种情况下,调用new
可能首先检查您的进程是否已在内部有足够的空间,如果没有,则从操作系统请求更多。无论返回什么内存都可以是物理的,或者它可以是虚拟的(在这种情况下,可能不会分配物理RAM来存储它直到它实际被访问)。你甚至无法区分,至少在没有使用特定于平台的API的情况下,因为内存硬件和内核会合谋将它隐藏起来。
2。这个“记忆”是什么?阵列中的空间?或其他什么?
在示例1中,它类似于数组中的空格:返回的地址标识可寻址的物理RAM块。即使在这里,RAM地址也不一定是平坦的或连续的 - 某些地址可能被保留用于ROM或I / O端口。
在示例2中,它是一个更虚拟的索引:您的进程的地址空间。这是一个抽象,用于隐藏进程中的底层虚拟内存详细信息。当您访问此地址时,内存硬件可能会直接访问某些实际RAM,或者可能需要请求虚拟内存子系统提供一些内容。
3。当这个“记忆”被分配时会发生什么?
通常,会返回一个指针,您可以使用该指针存储所需的字节数。在这两种情况下,malloc
或new
运算符都会进行一些内务处理,以跟踪流程的地址空间的哪些部分被使用以及哪些部分是免费的。
4。当内存被解除分配时会发生什么?
一般来说,free
或delete
会做一些内务管理,因此他们知道可以重新分配内存。
如果有人可以回答malloc在这些C ++行中所做的事情,那对我来说也会有所帮助:
char* x;
x = (char*) malloc (8);
它返回一个指针NULL
(如果它找不到你想要的8个字节)或一些非NULL值。
关于这个非NULL值的唯一有用的事情是:
x[0]..x[7]
,x[-1]
或x[8]
或实际任何 x[i]
是非法的(未定义的行为),除非0 <= i <= 7
x, x+1, ..., x+8
都是合法的(尽管你不能取消引用最后一个)x
会遇到它们答案 2 :(得分:3)
分配内存意味着向操作系统询问内存。这意味着程序本身只在需要时才在RAM中询问“空间”。例如,如果要在程序运行之前使用数组但不知道其大小,则可以执行以下两项操作: - 声明和数组[x]用x专用你,任意长。例如100.但是如果你的程序只需要一个包含20个元素的数组呢?你无所畏惧。 - 然后你编程可以在知道正确的x大小时malloc一个x元素的数组。 内存中的程序分为4个部分: -stack(调用函数时需要) -code(bibary可执行代码) - 数据(全局变量/数据) - heap,在这个段中你可以找到分配的内存。 当您决定不再需要分配的内存时,请将其返回给操作系统。
如果要分配10个整数的数组,请执行以下操作:
int * array =(int *)malloc(sizeof(int)* 10)
然后你把它还给了os 自由(数组)