精华内容
下载资源
问答
  • python怎么管理内存的

    千次阅读 2018-07-24 14:56:09
    先理解一下为什么要进行内存管理,内存管理是指软件运行时计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。 二、内存的分配方式 内存分配方式有...

    一、为什么进行内存管理

    先理解一下为什么要进行内存管理,内存管理是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。

    二、内存的分配方式

    内存分配方式有四种:

    (1)从静态存储区域分配。内存在程序编译的时候就已经分配好,存放全局变量和静态变量,这些内存在程序运行期间都存在。

    (2)在栈上创建。由编译器自动分配自动释放,用于存放局部变量和参数,栈内的对象先进后出,所以先创建的对象会后析构。栈由于是编译器自动管理的,所以栈内的对象不会存在内存泄露问题,并且效率很高,但是分配的内存容量有限。

    (3)从堆上分配,亦称动态内存分配。程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

    (4)常量区:存放常量字符串,程序结束后由系统释放

    三、python是怎么管理内存的:

    python的内存管理是由私有的heap空间管理的,所有的python对象和数据结构都在一个专有的heap(堆),程序员没有访问该heap的权限,只有解释器才能对他进行操作。

    而python的heap空间分配是由内存管理模块进行的,其核心API会提供一些访问该模块的方法提供程序员使用。

    python自带的垃圾回收系统,它会回收并释放没有被使用的内存,让她们能够被其他程序使用(内存池。被释放后先回到内存池然后再被别的程序所运用)

    展开全文
  • 内存管理

    2019-12-26 17:15:45
    内存管理是指软件运行时,对内存资源分配和使用技术,其最主要的目的是如何高效,快速分配内存,并且在适当时候释放和回收内存资源。 3.如何进行内存管理 iOS开发中数据一般是存储在堆和栈中,然后栈内存会...

    1.为什么需要管理内存
    移动设备的内存是有限的,每一个app所能占用的内存是有限的,如果不进行内存管理,那么app就会出现闪退,崩溃等情况。
    2.什么是内存管理
    内存管理是指软件运行时,对内存资源的分配和使用技术,其最主要的目的是如何高效,快速的分配内存,并且在适当的时候释放和回收内存资源。
    3.如何进行内存管理
    iOS开发中数据一般是存储在堆和栈中的,然后栈内存会自动回收,并不需要我们进行手动管理,因此,我们要管理的就是存放在堆内存中的数据。

    那么,堆和栈都是用来存储什么数据的呢?

    内存中有五大区域:栈,堆,BSS段,数据段,代码段,这五大区域的作用分别是:

    栈:用来存储局部变量
    堆:用来存储对象,允许程序员手动申请
    BSS段:未初始化的全局变量,静态变量
    数据段:初始化的全局变量,静态变量和常量
    代码段:代码
    

    因此,一般情况下,我们只需要关注对象什么时候创建,什么时候释放即可。

    4.引用计数器
    (1)什么是引用计数器?
    每个OC对象都有自己的引用计数器,它是一个整数
    可以理解为有多少个人正在使用或者被引用了多少次
    (2)系统是如何判断什么时候需要回收一个对象的?
    根据对象的引用计数器属。
    当对象的引用计数器为0时,这个对象就会被释放,只要这个对象的引用计数器不为0,就不会被释放。
    当创建(alloc,new,copy)一个对象的实例,并在堆内存上申请内存时,对象的引用计数器就为1。在其它对象中需要使用这个对象时,这个对象的引用计数器就会+1,需要释放一个对象时,就将这个对象的引用计数器-1,直到对象的引用计数为0,这个对象就会被自动释放
    (3)如何操作一个对象的引用计数器?
    给对象发送一个retain消息,可以使引用计数器值+1
    给对象发送一个release消息,可以使引用计数器-1
    给对象发送一个retainCount消息,可以方便程序员查看引用计数器的值,但是这个值并不都是正确的。

    注意:给对象发送release消息,并不代表这个对象就一定会释放,只有当对象的引用计数器为0时,这个对象才会释放。
    

    (4)dealloc方法
    dealloc是一个对象方法,dealloc方法和load,initialization是一样的,都不能手动调用,都是系统自动调用的。

    5.单个对象的内存管理

    int main(int argc, const char * argv[]){
        @autoreleasepool{
            Person *p = [[Person alloc] init];    //1
            //指针p是一个局部变量,所以p存储在栈中,Person对象存储在堆内存中,所以,当大括号结束的时候,p就会自动释放了,但是因为Person对象在堆内存中,并不会自动释放,所以,需要手动释放。
            [p release];    //如果直接这样写,会报错,因为是在ARC模式下,需要把程序切换到MRC模式下才不会报错。
            
        }
    }
    
    @implementation Person
    {
    
        -(void)dealloc{
            NSLog(@"%s", __func__);
        }
        [super dealloc];
    }
    

    注意:
    (1)ARC:Automatic Reference Counting(自动引用计数)
    不需要程序员管理,编译器xcode会在适当的地方自动加上release/retain等代码
    MRC:Matual Reference Counting(手动引用计数)
    需要手动添加release/retain等代码
    (2)将项目改成MRC模式的:项目->搜索Automatic Reference Counting改为NO

    内存管理的原则:一次alloc对应一次release,一次retain对应一次release,一次copy对应一次release,一次new对应一次release
    

    6.多个对象的内存管理

    存在依赖关系的对象之间的内存管理

    比如:

    @interface Room
    @property int no;
    @end
    @implementation Room
    
    -(void)dealloc{
       NSLog(@"%s",__func__);
    }
    @end
    
    @class Room;
    @interface Person : NSObject
    {
        Room *_room;
    }
    -(void)setRoom:(Room *)room;
    -(Room *)room;
    @end
    @implementation Person
    -(void)setRoom:(Room *)room{
       _room = room;
    }
    -(Room *)room{
       return _room;
    }
    -(void)dealloc{
       NSLog(@"%s",__func__);
    }
    @end
    
    int main(int argc, const char *argv[]){
       Person *p = [[Person alloc] init];
       Room *r = [[Room alloc] init];
       r.no = 888;
       p._room = r;
       [r release];
       [p release];
    
       
    }
    //如果只是这样写的话,
    

    图1
    当程序执行到第3行的时候,数据在内存中的存储形式如图1所示。

    当执行[r release]的时候,Room对象的retainCount减1,这时Room对象就会被释放。
    但是,此时Person对象还没被释放,Person对象还没有被释放时,Room对象是不能被释放的。因此,这样写是不对的。

    因此,对上面的代码进行修改

    @interface Room
    @property int no;
    @end
    @implementation Room
    
    -(void)dealloc{
       NSLog(@"%s",__func__);
    }
    @end
    
    @class Room;
    @interface Person : NSObject
    {
        Room *_room;
    }
    -(void)setRoom:(Room *)room;
    -(Room *)room;
    @end
    @implementation Person
    -(void)setRoom:(Room *)room{
       [room retain];   //当person对象使用room对象时,要对room对象的引用计数器加1
       _room = room;
    }
    -(Room *)room{
       return _room;
    }
    -(void)dealloc{
       NSLog(@"%s",__func__);
       [_room release];  //同时Person对象释放的时候,room对象也要释放
    }
    @end
    
    int main(int argc, const char *argv[]){
       Person *p = [[Person alloc] init];
       Room *r = [[Room alloc] init];
       r.no = 888;
       p._room = r;
       [r release];
       [p release];
    
       
    }
    

    这样修改之后,再执行上面的代码时,room对象的引用计数器会变成2。再执行[r release]和[p release]时,就不会存在person对象还存在的情况下,room对象已经销毁的情况了,同时,Person对象销毁的同时,room对象也要销毁,这样才不会造成内存泄露。

    接下来我们再看:

    @interface Room
    @property int no;
    @end
    @implementation Room
    
    -(void)dealloc{
       NSLog(@"%s",__func__);
    }
    @end
    
    @class Room;
    @interface Person : NSObject
    {
        Room *_room;
    }
    -(void)setRoom:(Room *)room;
    -(Room *)room;
    @end
    @implementation Person
    -(void)setRoom:(Room *)room{
       [room retain];   //当person对象使用room对象时,要对room对象的引用计数器加1
       _room = room;
    }
    -(Room *)room{
       return _room;
    }
    -(void)dealloc{
       NSLog(@"%s",__func__);
       [_room release];  //同时Person对象释放的时候,room对象也要释放
    }
    @end
    
    int main(int argc, const char *argv[]){
       Person *p = [[Person alloc] init];
       Room *r = [[Room alloc] init];
       Room *r1 = [[Room alloc] init];
       r.no = 888;
       p._room = r;
       p._room = r1;
       [r release];
       [p release];
    
       
    }
    

    图2
    如图2所示,换房的过程会造成内存泄露

    因此在更换取值之前,应该将之前的房间释放掉

    @interface Room
    @property int no;
    @end
    @implementation Room
    
    -(void)dealloc{
       NSLog(@"%s",__func__);
    }
    @end
    
    @class Room;
    @interface Person : NSObject
    {
        Room *_room;
    }
    -(void)setRoom:(Room *)room;
    -(Room *)room;
    @end
    @implementation Person
    -(void)setRoom:(Room *)room{
       if(_room != room){
             [_room release];   //需要将之前的取值释放掉
       }
       [room retain];   //当person对象使用room对象时,要对room对象的引用计数器加1
       _room = room;
    }
    -(Room *)room{
       return _room;
    }
    -(void)dealloc{
       NSLog(@"%s",__func__);
       [_room release];  //同时Person对象释放的时候,room对象也要释放
    }
    @end
    
    int main(int argc, const char *argv[]){
       Person *p = [[Person alloc] init];
       Room *r = [[Room alloc] init];
       Room *r1 = [[Room alloc] init];
       r.no = 888;
       p._room = r;
       p._room = r1;
       [r release];
       [p release];   
    }
    

    因此,setter方法最终的结果就是这样的了。如果对象的属性是一个对象,那就需要这样写setter和dealloc方法。

    7.property的修饰符

    retain:会自动帮我们生成setter/getter方法内存管理的代码
    assign:不会自动帮我们生成setter/getter方法内存管理的代码
    

    8.autorelease
    autorelease是一种支持引用计数的内存管理方式,只要给对象发送一条autorelease消息,会将对象放到一个自动释放池中,当自动释放池被销毁时,会对池子里的所有对象发送一条release消息

    @autoreleasepool {
     
            Person *p = [[Person alloc] init];
     
            [p autorelease];  
     
            //model can dongSomething you want
     
            NSLog(@"自动释放:end");
        } //自动释放池销毁
        //当执行到[p autorelease]时,对象会被加入到自动释放池中,当程序结束时,自动释放池会销毁,同时给池中的所有对象发送一个release消息
    

    其它写法

    //创建一个自动释放池
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    Person *p = [[[Person alloc] init] autorelease];
    [pool release];
    

    使用优点:
    再也不用考虑什么时候写release
    其实是延迟了对象的release

    在一个程序中可以使用多个自动释放池,多个自动释放池也可以嵌套使用

    @autoreleasepool{
       @autoreleasepool{
          @autoreleasepool{
               Person *p = [[Person alloc] init];
               [p run];
          }
       }
    }
    

    多个自动释放池是以栈的形式存储的。遵循先进后出的原则。
    给一个对象发送一条autorelease消息,那么会直接把对象放到栈顶的自动释放池。

    注意:
    (1) [p autorelease]会返回对象本身。
    (2) 自动释放池被销毁时,只是会给池子中的所有对象发送一个release消息,并不是销毁对象
    (3) autorelease并不会修改对象的引用计数器

    (4) autoreleasepool自动释放池可以创建多个
    (5) 一定要在自动释放池中调用autorelease,才会将对象放入自动释放池中
    (6)在自动释放池中创建了对象一定要调用autorelease,才会将对象放入自动释放池中
    (7)如果创建的对象只使用1次,以后就不用了,则不建议在autoreleasepool中使用
    (8)尽量不要在自动释放池中使用循环次数较多的对象
    (9)千万不要过度释放,一个alloc对应一个autorelease或者一个release。
    (10)Person *p = [[[Person alloc] init] autorelease] 可以一创建就使用autorelease
    (11)也可以使用类工厂方法,将autorelease封装到类工厂方法中,MRC模式下Foundation库中的类工厂方法都封装了autorelease

    展开全文
  • 关于内存管理

    2019-06-20 09:19:13
    在 iOS 中数据存在堆和栈中的,然而我们的内存管理管理的是堆上的内存,栈上的内存并不需要我们管理。 非OC对象(基础数据类型)存储在栈上 OC对象存储在堆上 引用计数 引用计数计算机编程语言中的一种内存管理...

    什么是内存管理?是指软件运行时对计算机内存资源的分配和使用技术。其最主要的目的就是如何高效、快速的分配,并且在适当的时候释放和回收内存资源。

    内存分配

    在 iOS 中数据是存在堆和栈中的,然而我们的内存管理管理的是堆上的内存,栈上的内存并不需要我们管理。

    • 非OC对象(基础数据类型)存储在栈上
    • OC对象存储在堆上

    引用计数

    引用计数是计算机编程语言中的一种内存管理技术,是指将资源(可以是对象、内存或磁盘空间等等)的被引用次数保存起来,当被引用次数变为零时就将其释放的过程。使用引用计数技术可以实现自动资源管理的目的

    MRC的四个法则

    • 自己生成的对象,自己持有。
    • 非自己生成的对象,自己也能持有。
    • 不在需要自己持有对象的时候,释放。
    • 非自己持有的对象无需释放。

    ARC

    ARC其实也是基于引用计数,只是编译器在编译时期自动在已有代码中插入合适的内存管理代码(包括 retain、release、copy、autorelease、autoreleasepool)以及在 Runtime 做一些优化。

    所有权修饰符

    Objective-C编程中为了处理对象,可将变量类型定义为id类型或各种对象类型。 ARC中id类型和对象类其类型必须附加所有权修饰符。

    其中有以下4种所有权修饰符:

    • __strong
    • __weak
    • __unsafe_unretaied
    • __autoreleasing

    所有权修饰符和属性的修饰符对应关系如下所示:

    • assign 对应的所有权类型是 __unsafe_unretained
    • copy 对应的所有权类型是 __strong
    • retain 对应的所有权类型是 __strong
    • strong 对应的所有权类型是 __strong
    • unsafe_unretained对应的所有权类型是__unsafe_unretained
    • weak 对应的所有权类型是 __weak


    __strong 表示强引用,对应定义 property 时用到的 strong。当对象没有任何一个强引用指向它时,它才会被释放

    __weak 表示弱引用,对应定义 property 时用到的 weak。弱引用不会影响对象的释放,而当对象被释放时,所有指向它的弱引用都会自动被置为 nil,这样可以防止野指针

    __weak 的几个使用场景:

    • 在 Delegate 关系中防止循环引用。
    • 在 Block 中防止循环引用。
    • 用来修饰指向由 Interface Builder 创建的控件。比如:@property (weak, nonatomic) IBOutlet UIButton *testButton;。

    ARC 是在 iOS5 引入的,而 __unsafe_unretained 这个修饰符主要是为了在ARC刚发布时兼容iOS4以及版本更低的系统,因为这些版本没有弱引用机制。这个修饰符在定义property时对应的是unsafe_unretained__unsafe_unretained 修饰的指针纯粹只是指向对象,没有任何额外的操作,不会去持有对象使得对象的 retainCount +1。而在指向的对象被释放时依然原原本本地指向原来的对象地址,不会被自动置为 nil,所以成为了野指针,非常不安全。

    在ARC中做内存管理主要就是发现这些内存泄漏,关于内存泄漏Instrument为我们提供了 Allocations/Leaks 这样的工具用来检测。

    这里有一个微信读书团队开源的工具MLeaksFinder,它可以在你程序运行期间,如果有内存泄漏就会弹出提示告诉你泄漏的地方。

    展开全文
  • python内存管理

    2019-05-24 10:22:13
    2,内存管理的主要目的 高效快速的分配,并且在适当的时候释放和回收内存资源 3,内存管理的三种机制 (1),引用计数器机制 原理:   Python内部记录着所有对象的引用数量,该数量使用一个内部跟踪变量存储,这...

    Python内存管理

    1,什么是内存管理?

    内存管理是指在软件运行时,对计算机内存资源的分配和使用的技术

    2,内存管理的主要目的

    高效快速的分配,并且在适当的时候释放和回收内存资源

    3,内存管理的三种机制

    (1),引用计数器机制

    原理:
      Python内部记录着所有对象的引用数量,该数量使用一个内部跟踪变量存储,这个跟踪变量就是引用计数器。一但单旦对象被创建,它对的引用计数器数值从0变成1。对象的引用计数随着对象引用数量的增加而增加。对象的引用数量每增加一个,引用计数器的值就增加1。反之,对象的引用数量没减少一个,引用计数器的值就会减少1,直到对象的引用计数器的值变成0时,就会被当做垃圾进行回收。

    (2),垃圾回收机制

      当内存中不再使用某个对象时,垃圾收集器就会把他们清理掉,它会去检查哪些引用计数器值为0的对象,然后清理其所在的内存空间。

    (3),内存池机制

      Python垃圾回收机制会清理不再使用的内存,但它并不是将不用的内存返回给操作系统,而是放到内存池中,内存池机制用于管理小块内存的申请和释放。

    4,引用计数机制的不足与解决方案

    不足:

    1. 降低垃圾回收的效率
    2. 不能解决循环引用问题

    解决方案:
      垃圾回收机制采用引用计数计数为主,标记-清除和分代收集计数为辅对垃圾收集功能进行完善。

    展开全文
  • Python内存管理

    2019-05-24 02:23:10
    2,内存管理的主要目的 高效快速的分配,并且在适当的时候释放和回收内存资源 3,内存管理的三种机制 (1),引用计数器机制 原理:   Python内部记录着所有对象的引用数量,该数量使用一个内部跟踪变量存储,这...
  •  内存管理是指软件运行时计算机内存资源分配和使用技术。其最主要的目的是如何高效、快速分配,并且在适当时候回收内存资源。 1、内存分配方式 内存分配方式有三种; (1)从静态存储区域分配。内存在...
  • 存储管理主要是指对内存储器的管理,负责对内存的分配和回收,内存的保护和扩充。 目的:存储管理主要是为了尽量提高内存的使用效率。 存储管理方式(5种) 单一连续区管理 在单道程序系统中,内存区域的用户...
  • 内存管理是指软件运行时计算机内存资源分配和使用技术,其最主要的目的是如何高效,快速分配,并且在适当时候释放和回收内存资源。 1)内存分配方式内存分配方式有三种: (1)从静态存储区域分配。...
  • 内存管理总结

    2015-10-14 13:21:14
    内存管理 内存管理是指软件运行时计算机内存资源分配和使用技术。其最主要的目的是如何高效,快速分配,,并且在适当时候释放和回收内存资源。 (一)为什么要进行内存管理。 由于移动设备的内存...
  • 存储管理主要指对内存的管理,即如何分配内存给不同的进程。 1.物理内存。 这最简单的方式,进程直接使用物理地址,实现很简单,但是不利于多程序系统,因为一个程序对某一物理地址的修改可能影响到其他的进程,...
  • 想必学过汇编语言朋友程序计数器这个概念并不陌生,在汇编语言中,程序计数器是指CPU中寄存器,它保存是程序当前执行指令地址(也可以说保存下一条指令所在存储单元地址),当CPU需要执行指令时,...
  • 计算机系统内存管理

    2018-11-11 12:28:10
    计算机系统内存管理 ...物理内存通常是具有掉电就丢失高速RAM构成,而虚拟内存通常是指在硬盘上开辟一块区域。虚拟内存有三个主要的作用: 1.它将主存看成是一个存储磁盘上地址空间数据高速缓存...
  • 操作系统中的存储管理主要是指对主存的管理。 主存即内存,是指处理机可以直接存取指令和数 据的存储器。主存是现代操作系统进行操作的中心, 是计算机系统中的一种重要资源。作为系统资源管理 程序的操作系统,...
  • 每天五分钟,轻松备考系统...存储管理主要是指对内存的管理,目的是尽量提高内存的使用效率。 1.1 内存 内存是系统实际提供的存储单元组成的一个连续地址空间,处理器可以直接存取。其访问速度快,价格较高。 1.2 外...
  • 存储管理 存储管理主要是指对内存的管理,负责内存分配和回收,内存的保护和扩充。 *存储管理和目的是尽量提高内存的使用效率。 内存的分配方式有两种 *连续的分配方式 指为一个用户程序分配一个连续的内存空间。 ...
  • 操作系统内存管理

    2019-08-26 16:04:29
    分段主要是对用户程序进行分段处理,用户程序运行逻辑地址都是相对地址,为了避免使用相同地址,需要偏移基址+逻辑地址来进行从逻辑地址到内存可用物理地址映射,段表LDT就是用来存储偏移基址,每一个进程有...
  • 定义:内存管理是指软件运行时计算机内存资源分配和使用技术。其最主要的目的是如何高效,快速分配,并且在适当时候释放和回收内存资源。 在C++中内存分为5个区,分别是堆、栈、自由存储区、全局/静态...
  • OC内存管理

    2015-10-29 00:55:52
    本质原因因为对象和其他数据类型在系统中的存储空间不一样,其它局部变量主要存放于 栈中,而对象存储于堆中,当代码块结束时这个代码块中涉及所有局部变量会被回收, 向对象指针也被回收,此时对象已经没有指针...
  • 存储管理主要是指对内存的管理,负责内存分配和回收,内存的保护和扩充。 一、内存分配方式 1. 连续的分配方式:用户的程序分配到一个连续的内存空间。 (1)单一连续分配 (2)固定分区分配 (3)动态分区分配...
  • 本质原因因为对象和其他数据类型在系统中的存储空间不一样,其它局部变量主要存放于 栈中,而对象存储于堆中,当代码块结束时这个代码块中涉及所有局部变量会被回收, 向对象指针也被回收,此时对象已经没有指针...
  • 内存管理是指软件运行时计算机内存资源分配和使用技术。其最主要的目的是如何高效,快速分配,并且在适当时候释放和回收内存资源。  2.内存分配方式  1)从静态存储区域分配。内存在程序编译...
  • JVM运行时数据区包括线程共享区域和线程私有区域两大部分,线程共享区域主要是指堆和方法区(JDK8之后移除该区域,改为元数据空间),线程私有区域主要是指虚拟机栈、本地方法栈和程序计数器。 堆:线程共享的内存...
  • 3 内存管理本文描述的内存管理主要是指:解释器的内存值如何表示,如何读取和存放。事实上,如果用值类型去存储内存值,是很难做到一个统一内存值模型。 复杂方法如JCUTE、CRest实现(符合执行框架,和...
  • 操作系统的主要功能

    2019-03-20 14:01:00
    (3)存储管理:实质对存储 "空间" 的管理主要指对内存(主存)的管理; (4)设备管理:实质对硬件设备的管理,其中包括对输入输出设备的分配、启动、完成和回收; (5)进程管理:实质上对处理机执行 ...
  • 线程最主要的目的就是提高程序运行性能,线程可以使程序更加充分地发挥系统可用处理...定义: 对象状态是指存储在状态变量(例如实例或静态变量)中数据,而对象线程安全性则是对象行为和其规范是否完全一...
  • 存储器管理

    2020-06-27 21:46:06
    存储管理主要是对内存的管理。 研究存储器,对它进行有效管理,不仅直接影响存储器的利用率,而且对系统性能有重大影响。 程序的装入和链接 地址空间:程序编译时还没有装入内存,不能确定它在内存中的实际位置,...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 192
精华内容 76
关键字:

存储管理的主要是指对内存的管理