内存管理

.NET资源泄露与处理方案

China☆狼群 提交于 2019-12-05 14:14:32
.NET虽然拥有强大易用的 垃圾回收机制 ,但并不是因为这样,你就可以对资源管理放任不管,其实在稍不注意的时候,可能就造成了资源泄露,甚至因此导致系统崩溃,到那时再来排查问题就已经是困难重重。 一、知识点简单介绍 常见的资源泄露有: 内存泄漏:非托管资源没有释放、非静态对象注册了静态实例。 GDI泄露:字体。 句柄泄露:Socket或线程。 用户对象泄露:移除的对象未释放。 二、具体实例 1. 内存泄漏 很常见的现象是分不清哪些对象需要释放,对于控件、Stream等一些非托管资源也只管新增,却没有释放,功能是实现了,却埋了颗不小的雷。 private void button1_Click(object sender, EventArgs e) { for(int i=0;i<1000;i++) this.Controls.Add(new TabPage()); } private void button1_Click(object sender, EventArgs e) { new Form2.ShowDialog(); } 如果你觉得写这样的代码很Cool,很简洁,你在项目中也有这么写代码,那你就碰到大麻烦了,你试试在上面Form2中开个大一点的数组来检查内存,然后运行,按几下按钮,你就会发现,内存一直增加,即使你调用了GC也无济于事。所以,对于此类非托管资源要记住释放

CPU上下文切换详解

二次信任 提交于 2019-12-05 13:54:12
我们都知道CPU上下文切换,会增加系统负载。那什么是CPU上下文,为什么要切换? 什么是CPU上下文 我们都知道,Linux 是一个多任务操作系统,它支持远大于 CPU 数量的任务同时运行。当然,这些任务实际上并不是真的在同时运行,而是因为系统在很短的时间内,将 CPU 轮流分配给它们,造成多任务同时运行的错觉。 而在每个任务运行前,CPU 都需要知道任务从哪里加载、又从哪里开始运行,也就是说,需要系统事先帮它设置好 CPU 寄存器和程序计数器(Program Counter,PC)。 CPU 寄存器,是 CPU 内置的容量小、但速度极快的内存。而程序计数器,则是用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置。它们都是 CPU 在运行任何任务前,必须的依赖环境,因此也被叫做 CPU 上下文。 而这些保存下来的上下文,会存储在系统内核中,并在任务重新调度执行时再次加载进来。这样就能保证任务原来的状态不受影响,让任务看起来还是连续运行。 根据任务的不同,CPU的上下文切换可以分为不同的场景,也就是进程上下文切换、线程上下文切换、中断上下文切换。 进程上下文切换 Linux 按照特权等级,把进程的运行空间分为内核空间和用户空间,分别对应着下图中, CPU 特权等级的 Ring 0 和 Ring 3。 内核空间(Ring 0)具有最高权限,可以直接访问所有资源;

Sun HotSpot JVM内存管理及垃圾收集

£可爱£侵袭症+ 提交于 2019-12-05 11:21:16
转自:http://blog.csdn.net/watchnight/archive/2009/12/11/4987065.aspx 内存模型(内存池) 从上图可以看出,一个java进程主要分为“Java Heap”和“C Heap”两个部分。只有“Java Heap”是JVM的GC对象。 从J2SE 5.0开始,JVM启动时会默认选择按“ server VM ”启动还是按“ client VM ”,具体选择策略参照下面的连接。 Server-Class Machine Detection 启动方式选择好以后,开始选择GC方法,根据GC方法的不同,为每块内存池设置不同的默认值。关于GC方法的选择,参照下面的连接。 Garbage Collector Ergonomics 另外,JVM一共提供了4中GC方法,根据业务的不同,可以选择不同的GC方法。GC方法详细介绍,参见下面的连接。 Memory Management Whitepaper [pdf] 根据GC算法的不同,GC的名字,以及内存池的名字都不一样。 J2SDK 5提供了一些MXBean,通过这些MXBean可以取得具体的名字。 如:java.lang.management.GarbageCollectorMXBean和java.lang.management.MemoryMXBean (1)-XX:

linux c 内存泄露检测工具valgrind

痞子三分冷 提交于 2019-12-05 07:51:52
Linux c/c++ 上常用内存泄露检测工具有 valgrind, Rational purify 。 Valgrind 免费。 Valgrind 可以在 32 位或 64 位 PowerPC/Linux 内核上工作。 Valgrind 工具包包含多个工具,如 Memcheck,Cachegrind,Helgrind, Callgrind , Massif 。下面分别介绍个工具的作用: Memcheck 工具主要检查下面的程序错误: • 使用未初始化的内存 (Use of uninitialised memory) • 使用已经释放了的内存 (Reading/writing memory after it has been free ’ d) • 使用超过 malloc 分配的内存空间 (Reading/writing off the end of malloc ’ d blocks) • 对堆栈的非法访问 (Reading/writing inappropriate areas on the stack) • 申请的空间是否有释放 (Memory leaks – where pointers to malloc ’ d blocks are lost forever) • malloc/free/new/delete 申请和释放内存的匹配 (Mismatched use of

Lab2:物理内存管理

血红的双手。 提交于 2019-12-05 07:29:31
前言 现在内存管理的方法都是非连续内存管理,也就是结合段机制和分页机制 段机制 段地址空间 进程的段地址空间由多个段组成,比如代码段、堆栈段和符号表段等等 段对应一个连续的内存“块” 不同段在物理内存中是分散的二维结构 段访问 首先由CPU读取逻辑地址,逻辑地址由段号和段内偏移组成 通过段寄存器找到相应的段描述符获得段基址 然后由MMU判断长度是否符合,否则就引发内存异常 最后通过段基址和段内偏移找到真实的物理内存 页机制 页机制把真实的物理内存分为大小相同的基本分配单位,叫做页帧,再接着把逻辑地址空间也划分为大小相同的基本分配单位,页和帧的大小必须是一致的,最后再完成从页面到页帧的映射,也就是逻辑地址到物理地址的转换 页和页帧 页帧和段的寻址方式有点像,也就是当前帧的基地址再加上帧内偏移,当前帧的基地址也是由当前的帧号和每一帧的大小确定的 页的寻址也是相同,但是页号不一定等于帧号,所以也就是在页和帧之间还有一层地址映射 页表 页表就是保存了逻辑地址到物理地址之间的映射关系,逻辑地址中保存着页号和页内偏移,到页表中查询页帧最后得到真实的物理地址 每一个页面都会对应一个页表项,页表会随着进程的变化而变化,页表项不仅记录对应的页帧还保存了一些标志:存在位、修改位和引用位 页机制的性能问题 页机制存储管理机制在访问性能方面可能因为每一次的访问地址需要两次访问而造成低效

Lab3:虚拟内存管理

吃可爱长大的小学妹 提交于 2019-12-05 07:29:30
前言 虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。 覆盖和技术 覆盖 依据程序逻辑结构,将程序划分为若干功能相对独立的模块;将不会同时执行的模块共享同一块内存区域 但是由于需要程序员来划分功能模块和确定模块之间的覆盖关系,所以增加了编程难度,并且也增加了执行时间 交换 交换技术和覆盖技术讨论的不一样的是,交换技术讨论的是当前内存足够当前的单个程序运行的内存,但是对于多道程序可能会有运行内存不够的情况 实现方法可以将暂时不能运行的程序放到外存当中,再运行时来执行换入换出操作 虚拟内存 在装载程序时,只将当前指令执行需要的部分页面或段装入内存,指令执行中需要的指令或数据不在内存(称为缺页)时,处理器通知操作系统将相应的页面调入内存,操作系统将内存中暂时不同的页面保存到外存 虚拟内存在页机制的基础上,也就是增加了请求调页和页面置换 当用户程序要装载到内存运行时,只装入部分页面,就启动程序运行 进程在运行中发现有需要的代码或数据不在内存时,则向系统发出缺页异常请求 操作系统在处理缺页异常时,将外存中相应的页面调入内存,使得进程能继续运行 页表项结构 驻留位:表示该页是否在内存 修改位:表示在内存中的该页是否被修改过 访问位

谈谈Java内存管理

半腔热情 提交于 2019-12-05 05:46:38
对于一个Java程序员来说,大多数情况下的确是无需对内存的分配、释放做太多考虑,对Jvm也无需有多么深的理解的。 但是在写程序的过程中却也往往因为这样而造成了一些不容易察觉到的内存问题,并且在内存问题出现的时候,也不能很快的定位并解决。 因此,了解并掌握Java的内存管理是一个合格的Java程序员必需的技能,也只有这样才能写出更好的程序,更好地优化程序的性能。 一、背景知识 根据网络可以找到的资料以及笔者能够打听到的消息,目前国内外著名的几个大型互联网公司的语言选型概括如下: Google: C/C++ Go Python Java JavaScript,不得不提的是Google贡献给java社区的guava包质量非常高,非常值得学习和使用。 Youtube、豆瓣: Python Fackbook、Yahoo、Flickr、新浪: php(优化过的php vm) 网易、阿里、搜狐: Java、PHP、Node.js Twitter: Ruby->Java,之所以如此就在于与Jvm相比,Ruby的runtime是非常慢的。并且Ruby的应用比起Java还是比较小众的。不过最近twitter有往scala上迁移的趋势。 可见,虽然最近这些年很多言论都号称java已死或者不久即死,但是Java的语言应用占有率一直居高不下。 与高性能的C/C++相比,Java具有gc机制

操作系统之存储管理_2019-11-20

眉间皱痕 提交于 2019-12-05 05:36:50
存储管理  早期计算机编程并不需要过多的存储管理  随着计算机和程序越来越复杂,存储管理成为必要   在存储管理中分为连续存储和非连续存储,非连续存储又分为分页存储、分段存储和段页式存储。  存储管理的目的:   确保计算机有足够的内存处理数据   确保程序可以从可用内存中获取一部分内存使用   确保程序可以归还使用后的内存以供其他程序使用  内存分配与回收   内存分配的过程    单一连续分配:     把内存分为系统区(被系统所使用)和用户区     只能在单用户、单进程的操作系统中使用    固定分区分配:     内存空间被划分为若干固定大小的区域,每个分区只提供给一个程序使用,互不干扰     支持多道程序的最简单存储分配方式     动态分区分配(最常用的内存分配方法):     根据进程实际需要,动态分配内存空间     相关 数据结构 (计算机存储、组织数据的方式 ):      (1)动态分区 空闲表 数据结构        存储使用情况,是否被使用,是否容量足够              (2)动态分区 空闲链 数据结构        把所有的空闲节点首尾相连,形成一个双向链表        可以把连续的空闲区合并为一个节点来减少节点数量              动态分区相关 分配算法:      首次适应算法(FF算法):      

python 内存管理

安稳与你 提交于 2019-12-05 05:03:59
python的内存管理 计数器 垃圾回收机制 垃圾回收:引用计数为主,标记清除和分带回收为辅 开启一个新的对象会存放到双端链表中 通过引用计数来决定是不是垃圾,但是会有循环引用的问题 为了解决循环引用,使用了标记清除,标记清除就是将循环引用的内容引用计数自动减一 为了解决多次扫描一个双端链表,使用了分袋回收,一共3个袋,0袋,1袋,2袋 当0袋的总长度>=700时扫描一下0袋,当0袋扫描10次后扫描一次1袋,扫描10次后计数仍大于等于1的进入1袋 当1袋扫描10次后扫描一次2袋,1袋扫描10次后计数仍大于等于1的进入2袋 内存池 a = 3.14 del a print(id(a)) b = 2.7 print(id(b)) #a和b的内存地址一样,因为有内存池的存在,浮点数和列表会使用和之前创建的对象同一内存地址 如何避免哈希冲突 可哈希? 如果一个对象在其生命周期内,其哈希值(可以通过python的内置函数hash获得)从未改变(这需要一个__hash__()方法),并且可以与其他对象进行比较(这需要一个__eq__()或__cmp__()方法),那么这个对象就是可哈希的。哈希对象的相等意味着其哈希值的相等。 哈希性使得对象可以用作dictionary键和set成员,因为这些数据结构在内部使用了哈希值。 Python的所有不可变的内置对象都是可hashable的,但可变容器

内存管理 (C++&c)

青春壹個敷衍的年華 提交于 2019-12-05 04:27:45
C/C++内存分布 C语言中动态内存管理方式 C++中动态内存管理 operator new与operator delete函数 new和delete的实现原理 定位new表达式(placement-new) 1. C/C++内存分布: 全局变量、static修饰的变量,都是存储在静态常量区的数据段;字符串保存在代码区,可读不可修改,malloc,calloc,realloc函数申请的空间在堆区,函数体内的局部变量保存在栈区。 2. C语言中动态内存管理方式: C语言中主要用malloc/calloc/realloc这三个函数申请空间,申请的空间都在堆上,都用free函数释放这些申请的空间。 用法: void test() { int num=10; //num表示空间要存放的元素个数 //返回值是void*类型,所以要自己根据需求强转 //一个参数,参数的值为申请的空间的字节数 int *p1 = (int*)malloc(sizeof(int)*num); //返回值是void*类型,所以要自己根据需求强转 //两个参数的乘积为申请的空间的字节数,不用手动将它们乘起来 int *p2 = (int*)calloc(num, sizeof(int)); //返回值是void*类型,所以要自己根据需求强转 //两个参数,第一个是旧空间指针,第二个参数的值是新空间的字节数 int