VirtualAlloc

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VirtualAlloc相关的知识,希望对你有一定的参考价值。

VirtualAlloc用法
VirtualAlloc用法

VC声明
LPVOID VirtualAlloc(
LPVOID lpAddress, // region to reserve or commit
SIZE_T dwSize, // size of region
DWORD flAllocationType, // type of allocation
DWORD flProtect // type of access protection
);
[编辑本段]
说明
该函数的功能是在调用进程的虚地址空间,预定或者提交一部分页
如果用于内存分配的话,并且分配类型未指定MEM_RESET,则系统将自动设置为0;
[编辑本段]
参数表说明
LPVOID lpAddress, 分配内存区域的地址。当你使用VirtualAlloc来提交一块以前保留的内存块的时候,lpAddress参数可以用来识别以前保留的内存块。如果这个参数是NULL,系统将会决定分配内存区域的位置,并且按64-KB向上取整(roundup)。
SIZE_T dwSize, 要分配或者保留的区域的大小。这个参数以字节为单位,而不是页,系统会根据这个大小一直分配到下页的边界DWORD
flAllocationType, 分配类型 ,你可以指定或者合并以下标志:MEM_COMMIT,MEM_AUTO_COMMIT,MEM_RESERVE和MEM_TOP_DOWN。
DWORD flProtect 指定了被分配区域的访问保护方式
分配类型 功能
MEM_COMMIT 在内存或者指定的磁盘页文件(虚拟内存文件)中分配一物理存储区域 函数初始化这个区域为0
MEM_PHYSICAL 该类型必须和MEM_RESERVE一起使用 分配一块具有读写功能的物理内存区
MEM_RESERVE 保留虚拟地址空间以便以后提交。
MEM_RESET
MEM_TOP_DOWN 告诉系统从最高可允许的虚拟地址开始映射应用程序。
MEM_WRITE_WATCH
访问类型
PAGE_READONLY 该区域为只读。如果应用程序试图访问区域中的页的时候,将会被拒绝访问PAGE_READWRITE 区域可被应用程序读写
PAGE_EXECUTE 区域包含可被系统执行的代码。试图读写该区域的操作将被拒绝。
PAGE_EXECUTE_READ 区域包含可执行代码,应用程序可以读该区域。
PAGE_EXECUTE_READWRITE 区域包含可执行代码,应用程序可以读写该区域。
PAGE_GUARD 区域第一次被访问时进入一个STATUS_GUARD_PAGE异常,这个标志要和其他保护标志合并使用,表明区域被第一次访问的权限
PAGE_NOACCESS 任何访问该区域的操作将被拒绝
PAGE_NOCACHE RAM中的页映射到该区域时将不会被微处理器缓存(cached)
注:PAGE_GUARD和PAGE_NOCHACHE标志可以和其他标志合并使用以进一步指定页的特征。PAGE_GUARD标志指定了一个防护页(guard page),即当一个页被提交时会因第一次被访问而产生一个one-shot异常,接着取得指定的访问权限。PAGE_NOCACHE防止当它映射到虚拟页的时候被微处理器缓存。这个标志方便设备驱动使用直接内存访问方式(DMA)来共享内存块。
[编辑本段]
返回值
如果调用成功,返回分配的首地址,
调用失败,返回NULL 你可以通过GetLastError函数来获取错误信息
[编辑本段]
笔记
VirtualAlloc可以通过并行多次调用提交一个区域的部分或全部来保留一个大的内存区域。多重调用提交同一块区域不会引起失败。这使得一个应用程序保留内存后可以随意提交将被写的页。当这种方式不在有效的时候,它会释放应用程序通过检测被保留页的状态看它是否在提交调用之前已经被提交

例子:
#include <windows.h>

void main()

SYSTEM_INFO sf;
GetSystemInfo(&sf);

//分配内存,标记为提交、可读可写
LPVOID lpvBase = VirtualAlloc(
NULL, // system selects address
4096, // size of allocation
MEM_COMMIT, // allocate reserved pages
PAGE_READWRITE); // protection = no access
if (lpvBase == NULL )
return;

//向该内存里面写些东西
unsigned char *ustr=(unsigned char *)lpvBase;
ustr[0]=0x89;

//修改为“只读”属性,验证是否能写入
DWORD dw;
VirtualProtect(lpvBase,4096,PAGE_READONLY,&dw);
// ustr[0]=0x44; //失败

//修改为“不可访问”,验证是否能读出
VirtualProtect(lpvBase,4096,PAGE_NOACCESS,&dw);
// dw = ustr[0]; //失败

return;

参考资料:http://baike.baidu.com/view/1521481.html?wtp=tt

参考技术A VirtualAlloc(
__in_opt LPVOID lpAddress,
__in SIZE_T dwSize,
__in DWORD flAllocationType,
__in DWORD flProtect
);
lpAddress是指定内存开始的地址。
dwSize是分配内存的大小。
flAllocationType是分配内存的类型。
flProtect是访问这块分配内存的权限。

void* pMem = ::VirtualAlloc(NULL, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
::VirtualFree(pMem, 0, MEM_RELEASE);
参考技术B virtualalloc建立一个动态数组

TCHAR* pszBuf=NULL;
pszBuf=(TCHAR*)VirtualAlloc(0,sizeof(TCHAR)*4096,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);

VirtualAlloc/Ex 分配啥样的内存

【中文标题】VirtualAlloc/Ex 分配啥样的内存【英文标题】:What kind of memory does VirtualAlloc/Ex allocateVirtualAlloc/Ex 分配什么样的内存 【发布时间】:2018-05-24 17:02:50 【问题描述】:

我知道 C/C++ 风格的程序有内存部分、堆栈、堆、.text 等。但是当我使用 VirtualAlloc 时,它从哪里分配内存?我不认为是堆,因为我可以使用 HeapAlloc。

建议将不胜感激!

【问题讨论】:

在虚拟地址空间中,这就是为什么它以virtual开头。请参阅VirtualAlloc documentation。 谢谢!最后一件事。如果我要分配大量内存来存储数据文件,我应该使用 VirtualAlloc 还是应该使用堆来代替? 非常大 == 虚拟。在现代操作系统(包括 Windows)上,它几乎(双关语)是无限的。 哈哈,好的,谢谢! 在 Windows 上,进程中的所有内存都是虚拟内存。在 C++ 中,堆栈(自动)和堆(动态)内存只是进程虚拟内存的子集。有关详细信息,请参阅 MSDN 上的 Thread Stack Size、Comparing Memory Allocation Methods 和 Managing Virtual Memory。 【参考方案1】:

堆内存驻留在您的程序虚拟内存中,由 VirtualAlloc 在后台分配。但是,问题在于 VirtualAlloc 仅在称为页面的大块中分配内存,这使得它无法用于一般的内存分配。

因此,HeapAlloc 管理已分配的页面,并且可以将多个分配连接到一个页面中,这样您就不必为每个小分配分配整个页面(通常为 4KB,但这不是规则)。

【讨论】:

【参考方案2】:

这是不正确的:

我知道 C/C++ 风格的程序有内存部分、堆栈、堆、.text 等。

此类部分仅通过系统系统上的链接和其他系统上的加载而退出。此上下文中的部分仅说明如何在内存中对应用程序的各个部分进行分组。当你的程序运行时,它只有内存。

像 VirtualAlloc 这样的函数只是将页面分配给进程。

【讨论】:

以上是关于VirtualAlloc的主要内容,如果未能解决你的问题,请参考以下文章