对 .NET程序2G虚拟地址紧张崩溃 的最后一次反思

news2024/11/14 20:24:11

一:背景

1. 讲故事

最近接连遇到了几起 2G 虚拟地址紧张 导致的程序崩溃,基本上 90% 都集中在医疗行业,真的很无语,他们用的都是一些上古的 XP,Windows7 x86,我也知道技术人很难也基本无法推动硬件系统和设备的升级,这里蕴含了巨大的人情世故。

写这一篇的目的是想系统化的整理一下如何配置 3G 开关让程序吃到更多的内存,让程序崩溃的不那么频繁一些,以及如何验证是否成功开启!

二:32位操作系统

1. 测试代码

首先大家要有一个理念:就是 32bit系统上跑的程序,默认只能吃到 2G 内存,因为这涉及到公平,用户态吃2G,内核态吃2G,为了方便演示,向一个 List 塞入 5000w 的 string,大概占用 2G 内存,然后把程序跑在 Windows7 32bit 操作系统上。


        static void Main(string[] args)
        {
            var list = new List<string>();

            for (int i = 0; i < 50000000; i++)
            {
                list.Add(i.ToString());

                if (i % 10000 == 0) { Console.WriteLine($"i={i}"); }
            }
            Console.WriteLine("ok");
            Console.ReadLine();
        }

从图中可以清楚的看到当内存到了631M 的时候就扛不住了,可能有些朋友好奇,为什么才这么点就不行了,这是因为 List 的底层是 2倍 扩容,所以内存大概会涨到 0.63G + 1.2G = 1.83G

有些朋友可能会问,这不是还没到2G吗?一般来说内存到了 1.2G+ 的时候崩溃风险就会剧增,这个要谨记!

2. 如何解决

刚才也说了,医疗行业现状如此,只能通过人情世故去推动,那这 2G 数据真的无处安放吗? 这时候就只能启动 3G 开关,那如何启动呢?

  1. 开启程序级的 Large Address Aware

这个 Large Address Aware 字段俗称大地址,途径就是在 PE 头里打开一个开关,让Windows加载器决定是否给程序打开 3G 的绿色通道。

当然看 PE头 的工具有很多,对于.NET程序个人感觉最好的就是用 DnSpy,它把 File Header 中的 Characteristics 字段具化了,我们选中 Large Address Aware 复选框然后保存,截图如下:

  1. 开启机器级别 3G 开关

在32bit操作系统上让用户态程序吃到 3G 内存这对操作系统来说是非常谨慎的,毕竟这对内核态是非常不公平的,言外之意就是让出自己的 1G 给用户态,这骚操作可能就会把自己坑惨,谨慎起见需要人工开启机器级别的 3G 开关,命令如下:


bcdedit /set IncreaseUserVa 3072

做了这两步之后,继续让程序跑起来,截图如下:

从图中可以清晰的看到,终于有出息了。

更多操作系统配置,可参考这篇文章:https://www.autodesk.com.cn/support/technical/article/caas/sfdcarticles/sfdcarticles/CHS/How-to-enable-a-3GB-switch-on-Windows-Vista-Windows-7-or-Windows-XP-s.html?v=2018

3. 如何验证是否开启了 3G

这确实是一个好问题,最简单的方式就是用!address 观察下地址空间。


0:000> !address

  BaseAddr EndAddr+1 RgnSize     Type       State                 Protect             Usage
-----------------------------------------------------------------------------------------------
...
+ bffde000 bffdf000     1000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~0; aa4.fb8]
+ bffdf000 bffe0000     1000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     PEB        [aa4]
+ bffe0000 bfff0000    10000 MEM_PRIVATE MEM_RESERVE PAGE_NOACCESS                      <unknown>  

0:000> ? bfff0000/0x100000
Evaluate expression: 3071 = 00000bff

上面卦中的 bfff0000 转换过来就是 3G,如果你看到的是这个值,那就恭喜你啦!

如果有朋友想问如何验证 dump程序是否开启了大地址,这个可以用windbg提供的 !dh 命令。


0:000> lm
start    end        module name
001e0000 001e8000   ConsoleApp4 C (pdb symbols)          D:\code\MyApplication\ConsoleApp4\obj\x86\Debug\ConsoleApp4.pdb
66dd0000 678c8000   mscorlib_ni   (deferred)             
678d0000 67e61000   mscorwks   (deferred)             
6c7a0000 6c83b000   msvcr80    (deferred)  
...
0:000> !dh ConsoleApp4

File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
     14C machine (i386)
       3 number of sections
EDB20AC7 time date stamp
       0 file pointer to symbol table
       0 number of symbols
      E0 size of optional header
     122 characteristics
            Executable
            App can handle >2gb addresses
            32 bit word machine

如果看到上面卦中的 App can handle >2gb addresses 字样就表示你开启成功啦!

三:64位操作系统

1. 如何吃更多内存

在 x64系统上就方便多了, 只需要做第一步开启 Large Address Aware 即可,毕竟 x64系统 的虚拟地址空间不要太充足,在 48根地址总线上就是2的48次方,所以开启大地址后,会给 x32 程序4G的寻址空间,即 2 的 32 次方。

接下来直接把刚才的 ConsoleApp4.exe 程序从 Windows7 x86 搬迁到 Windows 10 x64 系统上,然后用 windbg 附加运行, 跑完后使用 !address 查看。


0:007> !address 

  BaseAddr EndAddr+1 RgnSize     Type       State                 Protect             Usage
-----------------------------------------------------------------------------------------------
+        0   c60000   c60000             MEM_FREE    PAGE_NOACCESS                      Free     
...
+ ff671000 ff680000     f000             MEM_FREE    PAGE_NOACCESS                      Free       
+ ff680000 ff6b3000    33000 MEM_MAPPED  MEM_COMMIT  PAGE_READONLY                      Other      [NLS Tables]
+ ff6b3000 ffff0000   93d000             MEM_FREE    PAGE_NOACCESS                      Free       

0:007> ? ffff0000 /0x100000
Evaluate expression: 4095 = 00000fff

如果在你的卦中也看到了上面的 ffff0000 ,那就恭喜你,你程序的内存寻址空间扩展到了 4G 。

三:总结

本篇说了这么多,其实都是一些不得已而为之的事情,很心酸,这世上很多东西不是靠技术就能解决的,更需要靠人情事故!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1248956.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

XG916Ⅱ轮式装载机后驱动桥设计机械设计CAD

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;装载机 获取完整论文报告工程源文件 本次设计内容为XG916Ⅱ装载机后驱动桥设计&#xff0c;大致上分为主传动的设计&#xff0c;差速器的设计&#xff0c;半轴的设计&#xff0c;最终传动的设计四大部分。其中主传动锥齿轮…

读懂搜狐财报里的“生长密码”

自然界中各种植物的生长&#xff0c;在某些方面都合乎一定的数学规律。比如&#xff0c;斐波那契数列&#xff1a;树木各个年份对应的枝丫数、不同花朵的花瓣数量都对应着“1&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;5……”的数字。 科学家们认为&#xff0c;斐波…

最近iphone手机的交管12123闪退,打不开的解决办法?

苹果手机系统和新版软件不配&#xff0c;终极决绝办法&#xff1a;升级IOS系统就好 可能是手机的内存不足了&#xff0c;因为在使用APP时&#xff0c;需要占用手机的内存&#xff0c;如果手机内存不足以支持软件允许&#xff0c;软件就会闪退。车主可以清理一下手机的内存&…

高压配电室无人值守

高压配电室无人值守是指高压配电室在没有现场人员持续值守的情况下进行运行和管理。这种模式的实现依赖于先进的智能化技术和自动化系统&#xff0c;以确保配电室的安全、稳定和高效运行。 无人值守智能高压配电室的优势包括&#xff1a; 成本降低&#xff1a;无需常驻人员值守…

堆的实现(C语言版)

文章目录 概述堆的实现初始化销毁插入删除取堆顶元素求堆的长度判断堆是否为空 完整代码 概述 如果有一个关键码的集合K {k0,k1,k2…kn-1}&#xff0c;把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中&#xff0c;并满足&#xff1a;Ki <K2*i1 且 Ki<K2…

Fiddler 无法抓包手机 https 报文的解决方案来啦!!

解决手机https无法抓包的问题 当你测试App的时候&#xff0c;想要通过Fiddler/Charles等工具抓包看下https请求的数据情况&#xff0c;发现大部分的App都提示网络异常/无数据等等信息 这时候怎么解决呢&#xff1f; 以软件测试面试提刷题APP为例&#xff1a; Fiddler上的显示…

excel自己记录

1、清除换行符号 2、添加特殊符号&并清除换行符号 7日&15日&30日&60日 3、判断单元格最后一个字符是不是数字&#xff0c;不是就删掉 IF(ISNUMBER(--RIGHT(B2,1)),B2,SUBSTITUTE(B2,RIGHT(B2,1),"")) ISNUMBER(--RIGHT(B2,1))判断最右边的一个数是否…

【正点原子STM32连载】 第五十八章 手写识别实验(Julia分形)实验 摘自【正点原子】APM32F407最小系统板使用指南

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html## 第五…

[Python程序打包: 使用PyInstaller制作单文件exe以及打包GUI程序详解]

文章目录 概要Python 程序打包—使用 Pyinstaller 打包 exePython程序打包—使用Pyinstaller打包GUI程序Python程序打包—使用 Pyinstaller 设置 exe 图标小结 概要 使用PyInstaller工具将Python程序打包成可执行&#xff08;EXE&#xff09;文件。将Python程序打包成EXE的好处…

socket can中是如何根据 结构体can_bittiming_const中的字段 计算bitrate的?

在 SocketCAN 中&#xff0c;can_bittiming_const 结构体用于表示 CAN 总线的定时参数&#xff0c;包括位率&#xff08;bitrate&#xff09;的计算。can_bittiming_const 包含了许多与位率相关的参数&#xff0c;其中一些参数用于计算实际的位率。 下面是一些与位率计算相关的…

java中关键字 volatile 和 synchronized 有什么区别

java中 volatile 和 synchronized 有什么区别&#xff1f;

城市NOA到来时刻,车企密集上车NVIDIA

作者 |张祥威 编辑 |德新 基于双NVIDIA DRIVE Orin实现城市NOA&#xff0c;已是今天国内汽车行业的主流做法。 这款芯片获得广泛的市场认同&#xff0c;用时仅一年多。去年3月&#xff0c; NVIDIA DRIVE Orin正式投产&#xff0c;此后从造车新势力一路来到更多自主品牌的车内&…

初学vue3与ts:路由跳转带参数

index-router <!-- 路由跳转 --> <template><div><div class"title-sub flex"><div>1、用router-link跳转带参数id1&#xff1a;</div><router-link to"./link?id1"><button>点我跳转</button>&…

逆矩阵相关性质与例题

1.方阵的行列式&#xff1a;就是将方阵中的每一个元素转换至行列式中。 1.性质一&#xff1a;转置方阵的行列式等于转置前的行列式。&#xff08;对标性质&#xff1a;行列式与它的转置行列式相等&#xff09; 2.性质二&#xff1a;|ka||a|*k的n次方&#xff0c;n为方阵阶数。 …

MySQL表的操作『增删改查』

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; MySQL 学习 &#x1f383;操作环境&#xff1a; CentOS 7.6 阿里云远程服务器 &#x1f381;软件版本&#xff1a; MySQL 5.7.44 文章目录 1.创建表1.1.创建时指定属性 2.查看表2.1.查看表结构2.2.查看建表信息…

HTTP/2:多路复用、服务器推送和首部压缩的革命

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

IO多路转接之epoll

目录 一. epoll的实现原理 二. epoll的相关接口 2.1 epoll_create -- 创建epoll模型 2.2 epoll_ctl -- 对epoll模型进行控制 2.3 epoll_wait -- 等待epoll所关注的事件就绪 2.4 epoll相关接口的使用方法 三. Epoll服务器的模拟实现 3.1 EpollServer类的声明 3.2 Epoll…

模拟退火算法应用——求解函数的最小值

仅作自己学习使用 一、问题 需求&#xff1a; 计算函数 的极小值&#xff0c;其中个体x的维数n10&#xff0c;即x(x1,x2,…,x10)&#xff0c;其中每一个分量xi均需在[-20,20]内。因此可以知道&#xff0c;这个函数只有一个极小值点x (0,0,…,0)&#xff0c;且其极小值是0&…

智能对话手机版系统源码:附带完整的搭建教程

移动设备的普及和移动互联网的发展&#xff0c;手机已经成为人们日常生活中最常用的通信工具。因此&#xff0c;针对手机平台开发智能对话系统具有非常重要的意义。首先&#xff0c;手机用户可以更加方便地进行语音对话和信息交互&#xff0c;提高沟通效率。其次&#xff0c;手…

ctfshow sql

180 过滤%23 %23被过滤&#xff0c;没办法注释了&#xff0c;还可以用’1’1来闭合后边。 或者使用--%0c-- 1%0corder%0cby%0c3--%0c--1%0cunion%0cselect%0c1,2,database()--%0c--1%0cunion%0cselect%0c1,2,table_name%0cfrom%0cinformation_schema.tables%0cwhere%0ctable_…