09年计算机二级C语言辅导:C技巧(内存分配:更换策略,不要为难内存)

分类:计算机等级|

更新时间:2008-11-21|

来源:教育联展网

在32位机上(64位也是一样的,但是空间大很多),一个进程可以分配到4GB的虚拟内存,当然,其中2G给了内核,剩下2GB有一些分给了代码段、数据段,最后剩下的就是给我们程序员用的了,这样看来,一个应用程序若硬生生的读取2GB左右的数据是一个极限了。

不过事实并非如此,只要利用虚拟内存技术有时还是可以读取的。

先简单说说windows虚拟内存的思路:  所谓虚拟内存,就是事实上可能还没有得到实际内存的内存,如果CPU要访问一个虚拟内存,哪么操作系统得首先判断这个虚拟内存有没有获得实际内存。如果有,那大可以大大方方的读取,甚至写数据。

但若如果没有,操作系统就必须在实际内存上找到一块地方,建立起与要读取虚拟内存的映射关系,这样就可以读取了。当然若是找不到这么多实际内存,那么可以一些暂时还没用到的实际内存放到更低一级的硬盘临时空间上,腾出空间来,再建立与虚拟内存的映射关系。

当然了,比如要读取2GB的数据,在1G内存上是无论如何也没法找到足够空间建立映射关系的。我们当然不可能一次性读取2GB数据,所以引入“页”这个概念,即每次虚拟内存射到实际内存上的时候,都是按页大小映射的,这个页大小,与CPU有关,在X86上一般是4KB。

说到这,读取大型数据的思路就出来了,我们可以先分配虚拟内存,等到我们读或者写当中的一些数据的时候,再分配实际内存,由于这些都是在内存这一级操作,效率远比读写数据的时候再从硬盘取出来的高。

windows API让我们轻松做到这一点。

VirtualAlloc,可以申请到一个虚拟内存,或者实际映射到实际内存的内存。我们可以先申请虚拟内存,等到真的要读取某处数据的时候,再申请实际内存(建立映射关系)。

详细可以看MSDN,下面给出一个示例代码:  #include

#include

#include

struct Sheet //我们要读取的数据结构

{

int nSize;

BOOL bVisible;

char big[1024 * 15];

std::string strText;

};

int main()

{

SYSTEM_INFO si;

GetSystemInfo(&si);

DWORD dwPageSize = si.dwPageSize; //获得CPU读取的页大小

//把页的单位转为字节(页的单位本来是KB,而我们的数据结构是按字节算的)

DWORD dwPageAsByte = dwPageSize * 1024;

//以下dwOccupy获得一个数据结构所占的空间,由于是按页分配实际内存,这样所占空间并定是页的整数倍

DWORD dwMod = sizeof(Sheet) % dwPageAsByte;

DWORD dwOccupy = 0;

if (dwMod != 0)

{

dwOccupy = (sizeof(Sheet) / dwPageAsByte) * dwPageAsByte + dwPageAsByte;

}

else

{

dwOccupy = sizeof(Sheet);

}

//申请虚拟内存,MEM_RESERVE表示不会和实际内存建立映射关系

LPVOID lpBaseAddr = VirtualAlloc(NULL, dwOccupy * 50, MEM_RESERVE, PAGE_READWRITE);

if (lpBaseAddr == NULL)

{

return 1;

}

__try

{

DWORD dwIndex = 0;

//以下不断的输入要读取哪个数据,若此数据还有没有建立实际内存映射关系,那么建立

while(true)

{

std::cout << "input the sheet number to write: ";

std::cin >> dwIndex;

//根据输入的索引,计算出所要读取的数据结构所在地址,注意同样是按页分配的

LPVOID lpSheetAddr = (LPVOID)((DWORD)lpBaseAddr + (dwIndex - 1) * dwOccupy);

MEMORY_BASIC_INFORMATION mbi;

memset(&mbi, 0, sizeof(mbi));

//查询内存状态

if (VirtualQuery(lpSheetAddr, &mbi, sizeof(mbi)) == sizeof(mbi))

{

if (mbi.State == MEM_RESERVE)//属于reserve状态

{

//建立与实际内存的映射关系

LPVOID lpAlloc = VirtualAlloc(lpSheetAddr, dwOccupy, MEM_COMMIT, PAGE_READWRITE);

if (lpAlloc == NULL)

{

std::cout << "commit fails in reserve state\n";

}

else

{

std::cout << "commit successes in reserve state\n";

}

}

}

//建立成功,考试@大提示读/写数据

Sheet * pSheet = (Sheet*)lpSheetAddr;

pSheet->nSize = 9;

pSheet->strText = "hello world";

pSheet->bVisible = TRUE;

}

}

__except(EXCEPTION_EXECUTE_HANDLER)

{

}

//释放内存

VirtualFree(lpBaseAddr, 0, MEM_RELEASE);

}

当然,这其中用到了一个影响效率的VirtualQuery函数,其实可以用异常处理手段提高效率的,留待以后再说。

还可以添加删除代码,一些数据不再用到的时候,可以把虚拟内存状态重新置为MEM_RESERVE,这样可以节省实际内存。

计算机二级换c语言,09年计算机二级C语言辅导:C技巧(内存分配:更换策略,不要为难内存)...相关推荐

  1. 计算机三级考试监控回放,09年计算机三级辅导:禁用Vista下的硬盘监控警告

    09年计算机三级辅导:禁用Vista下的硬盘监控警告发布时间:2008-12-13 Vista会对硬盘可用空间进行监控,当磁盘空间不够时,Vista会在任务栏上显示警告信息.禁用此功能,其实只需: * ...

  2. C语言动态内存分配详解

    文章目录 前言 一.为什么存在动态内存分配 1.已掌握的内存开辟方式 2.上述开辟空间方式的特点 3.为什么存在动态内存分配 二.动态内存函数的介绍 1.malloc 2.free 3.calloc ...

  3. C语言中动态内存分配的本质是什么?

    摘要:C语言中比较重要的就是指针,它可以用来链表操作,谈到链表,很多时候为此分配内存采用动态分配而不是静态分配. 本文分享自华为云社区<[云驻共创]C语言中动态内存分配的本质>,作者: G ...

  4. 【C 语言】内存管理 ( 动态内存分配 | 栈 | 堆 | 静态存储区 | 内存布局 | 野指针 )

    相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...

  5. C/C++语言变量声明内存分配

    [cpp] view plaincopy <span style="font-family: Verdana, Arial, Helvetica, sans-serif; " ...

  6. c语言链表内存分配失败,链表的C语言实现之动态内存分配

    链表的C语言实现之动态内存分配 來源:互聯網  2008-06-01 02:05:07  評論 一.为什么用动态内存分配 但我们未学习链表的时候,假如要存储数量比较多的同类型或同结构的数据的时候,总是 ...

  7. 【C语言】动态内存分配详解

    目录 一.为什么有动态内存分配 二.动态内存分配函数 (1)malloc()函数 (2)calloc()函数 (3)realloc()函数 三.常见的动态内存错误 1.越界访问 2.内存泄漏 3.对N ...

  8. C语言数组用到的动态内存分配

    动态内存分配 在学习数组的过程中,在输入数组时,原本想过scanf定义数组的大小再输入数组的各值,却报错. 发现原因: 1.定义数组的时必须指定数组长度 2.数组长度是在编译期就必须决定的 所以此时需 ...

  9. C语言之内存模型以及动态内存分配

    目录 内存分区模型 C/C++内存开辟 按照程序运行前后分区 程序运行前 代码区 全局区 程序运行后 栈区 堆区 关于栈 栈与静态区(数据段) 动态内存分配 那么使用动态内存的好处在哪? 常见的内存使 ...

最新文章

  1. 深度学习100例-卷积神经网络(CNN)识别神奇宝贝小智一伙 | 第16天
  2. 使用netsh.exe命令配置TCP/IP
  3. lenze变频器怎么更改地址_S7-200 SMART PLC Modbus通信控制 V20变频器
  4. linux环境变量设置错误后,如何恢复
  5. Android中的一个定时任务的方法
  6. / ./ ../ 的区别
  7. 终于,我读懂了所有Java集合——map篇
  8. 打破多项世界记录  双11背后最大的力量是技术
  9. python 文件上传下载,python实现上传下载文件功能
  10. IoT、3D 扫描抢救巴黎圣母院!
  11. delete函数的动态解析
  12. R语言︱决策树族——随机森林算法
  13. 我与WCF有个约会之牵手篇-第一个WCF示例程序
  14. Vue:进入组件显示蒙版及文字,离开隐藏
  15. 用where导致group by分组字段的索引失效
  16. js 求数组中最小值
  17. pyspark入门---通过kmeans分析出租车数据并调用百度API进行可视化
  18. 天涯“大鹏金翅明王”语录
  19. 微信小程序 上传身份证图像限制
  20. 证券交易api 查询证券编码及基本上市信息

热门文章

  1. 风变python小课离线版_Python是个什么鬼?为什么医学生朋友圈里都是它!
  2. oracle数据库看开销,【Database】AIX系统下跟踪开销大的Oracle数据库进程
  3. Java到底是不是值传递
  4. linux服务器非root用户安装Anaconda,并配置tensorflow/pytorch
  5. 【python】lambda函数
  6. WORD如何修改自动编号的起始编号值?
  7. java 批量插入clob_SpringBoot系列(16)线程池Executors并发编程之批量查询-插入数据
  8. Android Studio开启虚拟机报错!emulator: ERROR: x86 emulation currently requires hardware acceleration!解决办法梳理
  9. android引入开源项目方法,和解决android-support-v4.jar冲突问题
  10. npm run test报错