1.申请内存的两种方式:
<1>通过VirtualAlloc/VirtualAllocEx(后面会介绍,两者在底层的实现相同)申请的: Private Memory
<2>通过CreateFileMapping映射的: Mapped Memory
这个图我们已经熟悉了,不过物理页有着Map和Private两种。Map是公有物理页,Private是私有物理页。所以物理内存只分为两种一种是自己独占物理页,一种是和别人共享物理页。
2.内存申请与释放:
LPVOID VirtualAlloc(
[in, optional] LPVOID lpAddress,//要分配的内存区域的地址
[in] SIZE_T dwSize,//分配的大小
[in] DWORD flAllocationType,//分配的类型 MEM_COMMIT MEM_RESERVE
[in] DWORD flProtect//该内存的初识保护属性
);
LPVOID VirtualAllocEx(
[in] HANDLE hProcess,
[in, optional] LPVOID lpAddress,
[in] SIZE_T dwSize,
[in] DWORD flAllocationType,
[in] DWORD flProtect
);
VirtualAlloc函数是在自己的进程里面申请内存
VirtualAllocEx函数可以指定一个进程id,就是可以在别的进程中申请
查阅文档看一下分配的类型:
我们主要用到
MEM_COMMIT:不但占用地址,还要物理内存(即占坑也需要物理页)
MEM_RESERVE:把需要的线性地址留出来,不过不需要物理内存(先把坑站着,不过不需要物理页)
下面我们尝试获取内存,示例代码:
#include"stdafx.h"
#include<stdio.h>
#include<Windows.h>
int main()
{
LPVOID p = VirtualAlloc(
NULL,//第一个参数我们可以指定一个地址,不过一般不需要因为我们不知道哪个地址已经被使用了,所以我们一般不用指定
0x1000*2,//分配的大小(以字节为单位),我们一般以页为基本单位(4kb就是4096个字节),
MEM_COMMIT,
PAGE_READWRITE//你希望你的物理内存有什么属性(查阅官方文档),我这里是可读可写
);
printf("%x\n", p);//打印出占用的地址
if (p == NULL)
{
printf("error");
}
else
{
printf("get");
}
return 0;
}
我们在调试的时候查看内存,没有分配内存的时候是这样
注意:这个地址是随便的,因为我不知道系统会占哪个内存,所以等打印出p后再去找
我们去找这个地址
可以看到已经分配了。
申请内存只有两种方式,一种是独占内存(如上),一种是分享物理页通过CreateFileMapping实现
下面我们再试试释放内存:使用函数VirtualFree
BOOL VirtualFree(
[in] LPVOID lpAddress, //指向要释放的页面区域的基址的指针。
[in] SIZE_T dwSize,
[in] DWORD dwFreeType
);
介绍一下第三个参数
MEM_DECOMMIT:保留虚拟地址保留,物理页不保留
MEM_RELEASE:都不保留(使用时第二个参数填0)
示例代码如下:
#include"stdafx.h"
#include<stdio.h>
#include<Windows.h>
int main()
{
LPVOID p = VirtualAlloc(
NULL,//第一个参数我们可以指定一个地址,不过一般不需要因为我们不知道哪个地址已经被使用了,所以我们一般不用指定
0x1000*2,//分配的大小(以字节为单位),我们一般以页为基本单位(4kb就是4096个字节),
MEM_COMMIT,
PAGE_READWRITE//你希望你的物理内存有什么属性(查阅官方文档),我这里是可读可写
);
printf("%x\n", p);
if (p == NULL)
{
printf("error");
}
else
{
printf("get");
}
VirtualFree(p, 0, MEM_RELEASE);
return 0;
}
释放前
释放后,
3.堆与栈
可能有疑问,我们在学c语言的时候使用的malloc不也是申请内存吗?其实malloc是从VirtualAlloc申请的内存中拿出一小块来使用。malloc是假申请,VirtualAlloc是真申请。
示例代码:
#include"stdafx.h"
#include<stdio.h>
#include<Windows.h>
int main()
{
int x = 0x12345678;
int* y = (int*)malloc(sizeof(int) * 128);
printf("栈:%x \n", &x);//局部变量等叫栈内存
printf("堆:%x \n", y);//用malloc申请的内存叫堆内存
getchar();
return 0;
}
其实无论是堆内存还是栈内存,我们操作系统启动时操作系统已经使用VirtualAlloc为我们申请了,就是你还没申请其实已经申请过了。
输出:
我们可以试一下不用malloc申请,其实不用的话操作系统也为我们申请好了(因为这个地址每次都是变的我就不尝试了)