VirtualAlloc

VirtualAlloc是一个Windows API函数,它包含在windows 系统文件Kernel32.dll中,编程时直接使用就可以了,不需要再下载。
  该函数的功能是在调用进程的虚地址空间,预定或者提交一部分页
  如果用于内存分配的话,并且分配类型未指定MEM_RESET,则系统将自动设置为0;

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_RESERVE和MEM_TOP_DOWN。
  DWORD flProtect 指定了被分配区域的访问保护方式
  分配类型 功能
  
可能的数值含义
MEM_COMMIT为0x1000分配指定保留的内存页的物理存储在内存或磁盘上的分页文件。该函数的内存初始化为零。
保留并承诺在一个步骤的页面,调用VirtualAlloc 的MEM_COMMIT | MEM_RESERVE 。
该函数将失败,如果你尝试提交一个还没有被保留页。由此产生的错误代码是ERROR_INVALID_ADDRESS
尝试提交一个已经提交的页面不会导致函数失败。这意味着你可以承诺不首先确定当前承诺在每一页的状态页面。
MEM_RESERVE0x2000保留在没有任何实际的物理存储在内存或磁盘上的分页文件分配一个进程的虚拟地址空间的范围。
你可以提交保留页的后续调用 VirtualAlloc的功能。保留并承诺在一个步骤的页面,调用VirtualAlloc 的 MEM_COMMIT | MEM_RESERVE 。
内存分配的功能,如其他的malloc LocalAlloc,不能使用的内存保留的范围,直到它被释放 。
MEM_RESET0x80000表示,在所指定的内存范围内的数据lpAddress的dwSize不再是利益。页面不应该被读出或写入到分页文件。然而,将再次使用的内存块后,所以它不应该decommitted的 。这个值不能使用任何其他的价值 。
使用这个值并不保证范围与经营MEM_RESET将包含零。如果你想的范围包含零,decommit内存,然后将它重新作出 。
当您指定MEM_RESETVirtualAlloc函数忽略了价值flProtect。但是,您仍然必须设置flProtect有效的保护价值,比如,PAGE_NOACCESS
VirtualAlloc的返回一个错误,如果你使用 MEM_RESET的内存范围映射到一个文件 。如果它被映射到分页文件共享视图是唯一可以接受的的 。
  分配类型 也可以是下列值
  
可能的数值含义
MEM_LARGE_PAGES0x20000000的分配内存使用大页面支持。
大小和对齐必须是一个大页面的最低多个 。要获得这个值,使用 GetLargePageMinimum的功能 。
MEM_PHYSICAL0x400000储备的地址范围,可用于地图地址窗口扩展(AWE)的网页。
此值必须使用MEM_RESERVE,并没有其他值。
MEM_TOP_DOWN0x100000在尽可能高的地址分配内存。这可以比普通的拨款速度较慢,尤其是当有许多分配。
MEM_WRITE_WATCH0x200000导致系统来跟踪分配的地区,都写在网页 。如果指定此值,则还必须指定MEM_RESERVE
要检索的网页已写入,因为该地区被分配或写跟踪状态被重置地址,调用 GetWriteWatch功能。要重置写跟踪状态,调用GetWriteWatchResetWriteWatch。写跟踪功能仍然启用,直到该地区被释放的内存区域。
  访问类型
  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可以通过并行多次调用提交一个区域的部分或全部来保留一个大的内存区域。多重调用提交同一块区域不会引起失败。这使得一个应用程序保留内存后可以随意提交将被写的页。当这种方式不在有效的时候,它会释放应用程序通过检测被保留页的状态看它是否在提交调用之前已经被提交
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C++ 中,可以使用 `VirtualAlloc` 函数来分配内存,并将其用作 Thunk 函数的代码。下面是一个示例代码,展示了如何使用 `VirtualAlloc` 来创建一个简单的 Thunk 函数: ```cpp #include <iostream> #include <windows.h> // 定义一个函数指针类型 typedef int (*FuncPtr)(int); // Thunk 函数 int __stdcall ThunkFunction(int num) { std::cout << "Thunk function called with parameter: " << num << std::endl; // 调用原始函数 return num * 2; } int main() { // 分配内存空间 DWORD dwSize = 4096; // 分配的内存大小,这里假设为 4KB LPVOID lpAddress = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // 将 Thunk 函数的代码复制到分配的内存中 memcpy(lpAddress, ThunkFunction, dwSize); // 创建函数指针并将其设置为分配的内存地址 FuncPtr thunk = (FuncPtr)lpAddress; // 使用函数指针调用 Thunk 函数 int result = thunk(5); std::cout << "Result: " << result << std::endl; // 释放分配的内存 VirtualFree(lpAddress, 0, MEM_RELEASE); return 0; } ``` 在这个示例中,我们使用 `VirtualAlloc` 函数分配了一块内存空间,大小为 4KB。然后,使用 `memcpy` 函数将 Thunk 函数的代码复制到这块内存中。 接下来,我们创建了一个函数指针 `thunk`,并将其设置为分配的内存地址。通过这个函数指针,我们可以调用 Thunk 函数。 最后,我们使用函数指针调用 Thunk 函数,并打印出结果。完成后,使用 `VirtualFree` 函数释放分配的内存。 需要注意的是,使用 `VirtualAlloc` 分配的内存需要适当地设置内存保护属性,以确保其可执行和可读写。在本示例中,使用了 `PAGE_EXECUTE_READWRITE` 属性,表示内存既可执行又可读写。具体的内存保护属性需要根据实际需求进行选择。 此外,需要注意 Thunk 函数的参数传递和调用约定,以及在不同平台和编译器下可能存在的差异。这些细节需要根据具体情况进行处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值