精华内容
下载资源
问答
  • 动态内存管理

    千次阅读 2009-02-19 09:17:00
    动态内存管理动态内存管理DMM(Dynamic Memory Management)是从Heap中直接分配内存和回收内存。有两种方法实现动态内存管理。一是显示内存管理EMM(Explicit Memory Management)。在EMM方式,内存从Heap中进行分配...

    动态内存管理



    动态内存管理DMM(Dynamic Memory Management)是从Heap中直接分配内存和回收内存。

    有两种方法实现动态内存管理。

    一是显示内存管理EMM(Explicit Memory Management)。
    在EMM方式,内存从Heap中进行分配,用完后手动回收。程序使用malloc()函数分配整数数组,并使用free()函数释放分配的内存。

    二是自动内存管理AMM(Automatic Memory Management)。
    AMM也可叫垃圾回收器(Garbage Collection)。Java编程语言实现了AMM,与EMM不同,Run-time system关注已分配的内存空间,一旦不再使用,立即回收。

    无论是EMM还是AMM,所有的Heap管理计划都面临一些共同的问题和前在的缺陷:
    1)内部碎片(Internal Fragmentation)
    当内存有浪费时,内部碎片出现。因为内存请求可导致分配的内存块过大。比如请求128字节的存储空间,结果Run-time system分配了512字节。

    2)外部碎片(External Fragmentation)
    当一系列的内存请求留下了数个有效的内存块,但这些内存块的大小均不能满足新请求服务,此时出现外部碎片。

    3)基于定位的延迟(Location-based Latency)
    延迟问题出现在两个数据值存储得相隔很远,导致访问时间增加。

    EMM往往比AMM更快。
    EMM与AMM比较表:
    ——————————————————————————————————————
                                     EMM                                        AMM
    ——————————————————————————————————————
    Benefits     尺寸更小、速度更快、易控制         stay focused on domain issues
    Costs        复杂、记账、内存泄露、指针悬空           不错的性能
    ——————————————————————————————————————

    早期的垃圾回收器非常慢,往往占用50%的执行时间。

    垃圾回收器理论产生于1959年,Dan Edwards在Lisp编程语言的开发时实现了第一个垃圾回收器。

    垃圾回收器有三种基本的经典算法:

    1)Reference counting(引用计数)
    基本思想是:当对象创建并赋值时该对象的引用计数器置1,每当对象给任意变量赋值时,引用记数+1;一旦退出作用域则引用记数-1。一旦引用记数变为0,则该对象可以被垃圾回收。
    引用记数有其相应的优势:对程序的执行来说,每次操作只需要花费很小块的时间。这对于不能被过长中断的实时系统来说有着天然的优势。
    但也有其不足:不能够检测到环(两个对象的互相引用);同时在每次增加或者减少引用记数的时候比较费时间。
    在现代的垃圾回收算法中,引用记数已经不再使用。

    2)Mark-sweep(标记清理)
    基本思想是:每次从根集出发寻找所有的引用(称为活对象),每找到一个,则对其做出标记,当追踪完成之后,所有的未标记对象便是需要回收的垃圾。
    也叫追踪算法,基于标记并清除。这个垃圾回收步骤分为两个阶段:在标记阶段,垃圾回收器遍历整棵引用树并标记每一个遇到的对象。在清除阶段,未标记的对象被释放,并使其在内存中可用。

    3)Copying collection(复制收集)
    基本思想是:将内存划分为两块,一块是当前正在使用;另一块是当前未用。每次分配时使用当前正在使用内存,当无可用内存时,对该区域内存进行标记,并将标记的对象全部拷贝到当前未用内存区,这是反转两区域,即当前可用区域变为当前未用,而当前未用变为当前可用,继续执行该算法。
    拷贝算法需要停止所有的程序活动,然后开始冗长而繁忙的copy工作。这点是其不利的地方。

    近年来还有两种算法:

    1)Generational garbage collection(分代)
    其思想依据是:
      (1) 被大多数程序创建的大多数对象有着非常短的生存期。
      (2) 被大多数程序创建的部分对象有着非常长的生存期。
    简单拷贝算法的主要不足是它们花费了更多的时间去拷贝了一些长期生存的对象。
    而分代算法的基本思想是:将内存区域分两块(或更多),其中一块代表年轻代,另一块代表老的一代。针对不同的特点,对年轻一代的垃圾收集更为频繁,对老代的收集则较少,每次经过年轻一代的垃圾回收总会有未被收集的活对象,这些活对象经过收集之后会增加成熟度,当成熟度到达一定程度,则将其放进老代内存块中。
    分代算法很好的实现了垃圾回收的动态性,同时避免了内存碎片,是目前许多JVM使用的垃圾回收算法。

    2)Conservative garbage collection(保守)

    哪一种算法最好?答案是没有最好。

    EMM作为很常用的垃圾回收算法,有5种基本方法:
    1)Table-driven algorithms
    表驱动算法把内存分为固定尺寸的块集合。这些块使用抽象数据结构进行索引。比如一个bit对应一个块,用0和1表示是否分配。不利因素:位映射依赖于内存块的尺寸;另外,搜索一系列的空闲内存块可能需要搜索整个bit映射表,这影响性能。

    2)Sequential fit
    顺序适应算法允许内存分为不同的尺寸。此算法跟踪已分配和空闲的Heap,标记空闲块的起始地址和结束地址。它有三种子分类:
      (1) First fit(首次适应)——分配找到的第一个适合内存请求的块
      (2) Best fit(最佳适应)——分配最适合内存请求的块
      (3) Worst fit(最不适应)——分配最大的块给内存请求

    3)Buddy systems
    Buddy systems算法的主要目的是加速已分配内存在释放后的合并速度。显示内存管理EMM使用Buddy systems算法可能导致内部碎片。

    4)Segregated storage
    隔离存储技术涉及到把Heap分成多个区域(zone),并为每个区域采用不同的内存管理计划。这是很有效的方法。

    5)Sub-allocators
    子配置技术尝试解决在Run-time System下分配大块内存并单独管理的内存分配问题。换句话说,程序完全负责自己的私有存储堆(stockpile)的内存分配和回收,无需run-time System的帮助。它可能带来额外的复杂性,但是你可以显著地提高性能。在1990年的《C Compiler Design》一书中,Allen Holub就极好地利用了Sub-allocators来加速其编译器的实现。

    注意,显示内存管理EMM必须是灵活的,能够响应数种不同类型的请求。

    最后,使用EMM还是使用AMM?这是一个Religious question,凭个人喜好。EMM在复杂的开销下实现了速度和控制。AMM牺牲了性能,但换来了简单性。


    展开全文
  • C++模拟动态内存管理

    万次阅读 2018-05-17 22:20:24
    使用链表对进程进行存储,每个节点记录、 下一个进程的占用内存的大小 起始地址 执行时间 下一个进程的地址 随机生成进程(空间大小、执行时间) ...* title :C++模拟动态内存管理 * author ...

    使用链表对进程进行存储,每个节点记录、
    下一个进程的占用内存的大小
    起始地址
    执行时间
    下一个进程的地址
    随机生成进程(空间大小、执行时间)
    先执行连续内存分配,若内存分配到最后位置,则在之前产生的碎片中找可以容纳该进程的碎片放入。
    若没有找到这样的碎片就等待已经占用内存的进程退出空间之后再进入。

    代码如下

    /**
    * title :C++模拟动态内存管理
    * author : liyunhao
    * date:2018.05.17
    * time : 0:26
    */
    
    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    #include <windows.h>
    using namespace std;
    /公用函数
    //控制输出的位置
    void gotoxy(short x, short y)
    {
        static COORD cd;
        HANDLE g_hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
        cd.X = (short)(x << 1);
        cd.Y = y;
        SetConsoleCursorPosition(g_hConsoleOutput, cd);
    }
    
    int getRandom(int a,int b){//返回指定范围的随机数
        int range = b - a;
        if(range<=0){
            return 0;
        }else{
            return a + rand()%range;
        }
    
    }
    
    
    class Memory{
    public:
        int *p;
        int len;
        int CurrPos;
        Memory(int n=500){
            len = n;
            CurrPos = 0;
            p = new int [n];
            memset(p,0,4*n);
        }
        /
        int findAPos(int proLen){
            int pos = CurrPos;
            int start;
            int end;
            start = pos;
            while(p[start]==1 && start < len){
                start++;
            }
            end = start;
            while(p[end]==0){
                end++;
            }
            if(end-start > proLen && end <len){
                return start;
            }
    
        }
        bool MemoCanBeWrote(int s,int len){
            for(int i=s;i<s+len;i++){
                if(p[i]){
                    return false;
                }
            }
            return true;
        }
    
        bool writeMemo(int s,int len){
    
            for(int i=s;i<s+len;i++){
                p[i]=1;
            }
    
            CurrPos = s+len;
            CurrPos %= this->len;
        }
    
        bool clearMemo(int s,int len){
            for(int i=s;i<s+len;i++){
                p[i]=0;
            }
        }
    
        void disp(){
    
            gotoxy(1,1);
            for(int i=0;i<len;i++){
    
                cout<<p[i];
                if(i!=0 && (i+1)%100==0){
                    cout<<endl;
                    gotoxy(1,i/100+2);
                }
            }
            cout<<endl;
        }
    };
    
    class Process{
    public:
        int pid;
        int meSize;
        int meStart;
        int time;
        int nextPro;
        Process(int pid,int meSize,int time){
            this->pid = pid;
            this->meSize = meSize;
            this->time = time;
        }
    };
    
    class MemoMange{
    public:
        Memory * Memory1;
        vector<Process *> ProcVector;
        MemoMange(){
            Memory1 = new Memory;
        }
        int FindRoomForPro(int proLen){
            vector<Process *>::iterator iter;
            if(ProcVector.size() ==0 && proLen<Memory1->len){
                return 0;
            }
            iter =ProcVector.end()-1;
            if(Memory1->MemoCanBeWrote( (*iter)->nextPro,proLen )){
                return (*iter)->nextPro;
            }else{
    
                for(iter=ProcVector.begin();iter!=ProcVector.end()-1;iter++){
                    if(Memory1->MemoCanBeWrote( (*iter)->nextPro,proLen )){
                    return (*iter)->nextPro;
                    }
                }
                return -1;
            }
        }
        bool ProInComing(Process * pro){
            if(pro){
                int startOfNewPro = FindRoomForPro(pro->meSize);
                if(startOfNewPro >= 0){
    
                    Memory1->writeMemo(startOfNewPro, pro->meSize);
                    pro->meStart = startOfNewPro;
                    pro->nextPro = startOfNewPro + pro->meSize;
                    pro->nextPro %= Memory1->len;
                    //Memory1->CurrPos += pro->meSize;
                    ProcVector.push_back(pro);
                    gotoxy(1,7);
                    cout<<"进程"<<pro->pid<<"被创建"<<"并且成功写入内存"<<endl;
                }else{
                    gotoxy(1,7);
                    cout<<"进程"<<pro->pid<<"被创建"<<"但是无法写入内存"<<endl;
                }
                Memory1->disp();
            }
            else{
                cout<<"未知的进程"<<endl;
            }
        }
    
        bool ProLeaving(Process * pro){
             //在vector中查找指定元素
            vector<Process *>::iterator iter = find(ProcVector.begin(),ProcVector.end(),pro);
            //cout<<"pro->meStart"<<pro->meStart<<"pro->meSize"<<pro->meSize<<endl;
            Memory1->clearMemo(pro->meStart,pro->meSize);
            //删除指定元素
            gotoxy(1,8);
            cout<<"进程"<<pro->pid<<"被移出内存"<<endl;
            if(iter!=ProcVector.end())ProcVector.erase(iter);
            Memory1->disp();
    
        }
    
        bool ShortestProLeaving(){
             //在vector中查找指定元素
    
            vector<Process *>::iterator iter;
            vector<Process *>::iterator shortestIter;
            if(ProcVector.size() <= 0){
                return false;
            }
            iter = ProcVector.begin();
            shortestIter = iter;
            int shortest = (*iter)->time;
    
            while(iter != ProcVector.end()){
                if( (*iter)->time < shortest){
                    shortestIter = iter;
                    shortest = (*iter)->time;
                }
                iter++;
            }
            ProLeaving(*shortestIter);
            return true;
        }
        void disp(){
            vector<Process *>::iterator iter=ProcVector.begin();
            while(iter!=ProcVector.end())
            cout<<*iter++<<" ";
            cout<<endl;
        }
    };
    
    int main()
    {
        MemoMange MemoMange1;
        Process * p;
        gotoxy(20,0);
        cout<<"C++模拟动态内存管理"<<endl;
        int i=0;
        while(1){
    
            int randLen = getRandom(10,30);
            int action = getRandom(0,10);
            int randTime = getRandom(10,30);
            if(action<=7){
                p = new Process(i,randLen,randTime);
                MemoMange1.ProInComing(p);
            }else{
                MemoMange1.ShortestProLeaving();
    
            }
            Sleep(1000);
            i++;
        }
    
        return 0;
    }
    
    

    运行结果:
    ①起始状态
    这里写图片描述

    ②进程不断加入产生碎片,出现无法写入的情况,

    这里写图片描述

    ③一些进程退出,可以再次写入进程

    这里写图片描述

    展开全文
  • 05-C语言进阶——动态内存管理

    千次阅读 2020-11-25 10:50:05
    动态内存管理一、为什么要动态内存分配?二、动态内存函数函数介绍2.1malloc2.2 free2.3 calloc2.4 realloc三、常见动态内存错误3.1 对NULL指针的解引用操作3.2 对动态开辟空间的越界访问3.3 对非动态开辟内存使用...

    一、为什么要动态内存分配?

    前面用到的内存开辟方式为在栈上开辟空间,例如:

    int val = 20;//在栈空间上开辟四个字节
    char arr[10] = {0};//在栈空间上开辟10个字节的连续空间
    

    但是上述的开辟空间的方式有两个特点:

    • 空间开辟大小是固定的。
    • 数组在声明的时候,必须指定数组的长度,它所需要的内存在编译时分配
      但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组编译时开辟空间的方式就不能满足了。 这时候就只能试试动态存开辟了。

    二、动态内存函数函数介绍

    2.1malloc

    malloc用来开辟动态内存

    void * malloc(size_t size);
    

    这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针

    • 如果开辟成功,则返回一个指向开辟好空间的指针
    • 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查
    • 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
    • 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。

    2.2 free

    void free (void* ptr);
    

    free函数用来释放动态开辟的内存。

    • 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
    • 如果参数 ptr 是NULL指针,则函数什么事都不做
      malloc和free都声明在 stdlib.h 头文件中。 举个例子:
    //申请5个整形字节的动态内存
    int *p = (int *)malloc(5*sizeof(int));
    //若返回值为空,则申请失败
    if (NULL == p)
    {
    	printf("malloc error!\n");
    	return 1;
    }
    //若申请成功,为每个元素赋值
    for (int i = 0; i < 5; i++)
    {
    	p[i] = i;
    }
    printf("malloc success!\n");
    
    //打印释放前p的地址
    printf("before:%p\n",p);
    
    //释放动态开辟的内存
    free(p);
    
    //打印释放后p的地址
    printf("after:%p\n", p);
    

    在这里插入图片描述
    这里需要注意的几个点

    • 如上图所示,free前后指向的地址不发生任何变化,改变的只是指针和对应的内存的管理关系。一般再添加一句代码令指针为NULL。
    p = NULL;
    
    • 如下图所示释放后的地址空间明显大于申请时的空间,原因是申请时指针包含有其它元信息。可以发现使用malloc申请小块空间的成本较大,因此不推荐申请小块内存。
      在这里插入图片描述
      在这里插入图片描述

    2.3 calloc

    C语言还提供了一个函数叫 calloc , calloc 函数也用来动态内存分配。原型如下:

    void* calloc (size_t num, size_t size);
    
    • 函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0
    • 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。 举个例子:
    int *p = (int *)calloc(10, sizeof(int));
    if (NULL != p)
    {
    	printf("success!\n");
    }
    
    free(p);
    p = NULL;
    

    在这里插入图片描述

    2.4 realloc

    realloc函数的出现让动态内存管理更加灵活。
    有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,为了合理使用内存,我们一定会对内存的大小做灵活的调整。realloc 函数就可以做到对动态开辟内存大小的调整。 函数原型:

    void * realloc(void * ptr, size_t size);
    
    • ptr 是要调整的内存地址
    • size 调整之后新大小
    • 返回值为调整之后的内存起始位置
    • 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到 新的空间
    • realloc在调整内存空间的是存在两种情况:
      • 情况1:原有空间之后有足够大的空间。当情况1 的时候,要扩展内存就在原有内存之后直接追加空间,原来空间的数据不发生变化
      • 情况2 :原有空间之后没有足够多的空间。扩展方法:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。 由于上述的两种情况,realloc函数的使用就要注意一些。 举个例
        子:
    	int *ptr = malloc(100);
    	if (ptr != NULL)
    	{
    		//业务处理
    	}
    	else
    	{
    		exit(EXIT_FAILURE);
    	}
    	//扩展容量
    	//代码1
    	ptr = realloc(ptr, 1000);//如果申请失败造成内存泄漏
    
    	//代码2
    	int*p = NULL;
    	p = realloc(ptr, 1000);
    	if (p != NULL)
    	{
    		ptr = p;
    	}
    	//业务处理
    	free(ptr);
    

    代码1的问题在于,如果realloc申请失败返回NULL指针,老空间ptr被置空,造成内存泄漏无法找到原有的内存地址。

    三、常见动态内存错误

    3.1 对NULL指针的解引用操作

    void test()
    {
        int *p = (int *)malloc(INT_MAX/4);
        *p = 20;//如果p的值是NULL,就会有问题
        free(p);
    }
    

    如果申请的空间较大可能造成malloc返回值为NULL

    3.2 对动态开辟空间的越界访问

    void test()
    {
        int i = 0;
        int *p = (int *)malloc(10*sizeof(int));
        if(NULL == p)
        {
            exit(EXIT_FAILURE);
        }
        for(i=0; i<=10; i++)
        {
            *(p+i) = i;//当i是10的时候越界访问
        }
        free(p);
    }
    

    3.3 对非动态开辟内存使用free释放

    void test()
    {
        int a = 10;
        int *p = &a;
        free(p);//错误
    }
    

    3.4 使用free释放一块动态开辟内存的一部分

    void test()
    {
        int *p = (int *)malloc(100);
        p++;
        free(p);//p不再指向动态内存的起始位置
    }
     
    

    3.5 对同一块动态内存多次释放

    void test()
    {
        int *p = (int *)malloc(100);
        free(p);
        free(p);//重复释放
    }
    

    3.6 动态开辟内存忘记释放(内存泄漏)

    void test()
    {
        int *p = (int *)malloc(100);
        if(NULL != p)
        {
            *p = 20;
        }
    }
     
    int main()
    {
        test();
        while(1);
    }
    
    展开全文
  • 首先我们先了解一下内存:C语言使用malloc/free动态管理内存空间,C++引入了new/delete,new[]/delete[]来动态管理内存。 介绍new/delete,new[]/delete[]之前我们先了解一下operator new,operator delete,...

    首先我们先了解一下内存:

    这里写图片描述

    C语言使用malloc/free动态管理内存空间,C++引入了new/delete,new[]/delete[]来动态管理内存。
    介绍new/delete,new[]/delete[]之前我们先了解一下operator new,operator delete,operator new[],operator delete[]函数。

    注:这些函数并没有重载new/delete表达式。

    函数声明如下:
    void* operator new(size_t size);
    void operator delete(size_t size);
    void* operator new[](size_t size);
    void operator delete[](size_t size);
    
    析:operator new/operator delete,operator new[]/operator delete[]是标准库函数,用法和malloc/free的用法一样,只负责分配/释放空间,但实际上operator new/operator delete只是malloc/free的一层封装。

    new/delete:动态管理对象;
    new[]/delete[]动态管理对象数组。

    int* ptr1=new int;//动态分配4个字节的空间
    delete ptr;
    int* ptr2=new int(4);//动态内存分配4个字节空间并初始化
    delete ptr2;
    int* ptr3=new int[4];//动态内存分配16个字节空间
    delete[];

    1>,new/delete实际上做了什么事呢??
    new:先调用operator new分配空间,再调用构造函数初始化空间。
    delete:先调用析构函数清理对象,再调用operator delete释放空间。

    这里写图片描述
    这里写图片描述

    2>,new[]/delete[]实际上做了什么事呢??
    new[n]:调用operator new分配空间,再调用n次构造函数初始化对象。
    delete[n]:调用n次析构函数清理对象,再调用operator delete释放空间。

    这里写图片描述

    为什么编译器会知道调用多少次构造函数,析构函数呢?
    原来在new[ ]分配空间的时候会在头部多分配4个字节来存n,这样在调用new[]/delete[]时就知道调用几次构造函数和析构函数了。

    new/delete,new[]/delete[]为什么要成对出现?
    当new在开辟内置类型的空间时,不成对出现是可以的;但是当开辟非内置类型空间时,就要多开辟4个字节,这时如果不成对使用就会造成内存泄漏或者程序崩溃。
    这里写图片描述

    用宏模拟实现new[]/delete[]申请和释放数组

    //DELETE_ARRAY参数中传n
    #define NEW_ARRAY(ptr,type,n)                          
    do{                             
    ptr=(type*)operatornew(sizeof(type)*n);             
    for (size_t i = 0; i <n;++i)                            
    {                       
    new(ptr+i)type;                     
    }                                                       
    } while (0);                                            
    
    
    #define DELETE_ARRAY(ptr,type,n)                
    do{                             
    for (size_t i = 0; i < n; ++i)                          
    {               
    (ptr+i)->~String();                        
    }                               
    operator delete ptr;                                
    } while (0);
    //给DELETE_ARRAY中不传n
    #define NEW_ARRAY(ptr,type,n)                           
    do{                                                                             
    ptr = (type*)operator new(sizeof(type)*n + 4);           //给n也分配空间
    *(int*)ptr = n;                                             
    ptr=(type*)((char*)ptr+4);                                  
    for (size_t i = 0; i < n; ++i)                              
    {                                                       
    new(ptr + i)(type);                                 
    }                                                           
    } while (0);
    
    #define DELETE_ARRAY(ptr,type)                              
    do{                                                         
        size_t n = *((int*)ptr - 1);                            
        for (size_t i = 0; i < n; ++i)                              
        {                                                           
        (ptr + i)->~String();                                  
        }                                                           
        operator delete(char*(ptr - 4));                            
    } while (0);

    malloc/free和new/delete之间关系和差异
    关系:都能进行动态内存管理。
    差异:1>,malloc/free是标准的库函数, new/delete是操作符;
    2>,malloc/free只是分配/释放内存 ,new/delete不仅分配/释放内存还调用构造函数初始化和析构函数清理;
    3>,malloc/free手动计算类型大小,返回值void*,new/delete自动计算类型大小,返回对应类型的指针;
    4>,malloc/free失败返回0, new/delete失败抛异常。

    展开全文
  • 动态内存管理——知识点小集结

    千次阅读 热门讨论 2021-03-24 10:07:07
    动态内存管理动态内存管理动态内存函数介绍mallocfreecallocrealloc经典的动态内存错误柔性数组 在发布通讯录的第二个版本,也就是动态版本之前,对于不了解动态内存的小伙伴来说,你们可以先看一看这篇博客,然后...
  • LwIP 之五 详解动态内存管理 内存堆(mem.c/h)

    千次阅读 多人点赞 2018-05-13 11:24:56
    LwIP为了能够灵活的使用内存,为使用者提供两种简单却又高效的动态内存管理机制:动态内存堆管理(heap)、动态内存池管理(pool)。这两中内存管理策略的实现分别对应着源码文件mem.c/h和memp.c/h。   其中,...
  • UCOS-II的动态内存管理

    千次阅读 2015-12-16 18:58:08
    UCOS-II嵌入式操作系统 动态内存管理
  • 动态内存管理详解

    千次阅读 2018-11-29 14:56:56
    C语言中开辟内存有很多种方式,目前我们最常用的也就是数组,但数组是在我们用到他之前就得设定好它的长度,... 所以,为了填补这一缺口,c语言有了动态内存,c语言提供了几个函数来管理我们的动态内存,这几个函数...
  • 两年前一位同事和我说过,单片机不能实现动态内存管理,两天后我在keil上利用malloc()在coterx m3芯片上实现了一个链表,然后把代码给他看了,对固执的人摆事实好过讲道理。之后我觉得使用malloc()并不能满足我的...
  • 【C解析之八】 动态内存管理

    千次阅读 2014-03-21 19:30:43
    C解析之八动态内存管理  前言:动态内存管理,C/C++迷人的魅力所在,只因,它可以让你对计算机的操控上升到近乎无限的程度。  动态内存管理和指针,实现C/C++对内存的精准操控,这一特征让C/C++程序在空间消耗上的...
  • 写在前面   写这篇文章时,网上已经有了铺天盖地的文章来介绍 FreeRTOS 的动态...  FreeRTOS 支持 5 种动态内存管理方案,分别通过文件 heap_1.c,heap_2.c,heap_3.c,heap_4.c 和 heap_5.c 实现。这 5 个文件...
  • C++ 动态内存管理

    千次阅读 2017-07-23 00:10:45
    (3)从堆或自由存储空间上分配,亦称为动态内存分配,如malloc函数和new运算符申请的内存(使用free和delete释放动态内存)。2、常见的内存错误及其对策 (1)错误:内存分配未成功,却使用了它。 对策:在使用...
  • [UC/OS-II原理及应用]动态内存管理

    千次阅读 2016-10-02 23:08:41
    第七章 动态内存管理 7.1 内存控制块 μC/OS-Ⅱ对内存进行两级管理,即把一个连续的内存空间分为若干各分区,每个分区分为若干个大小相等的内存块。操作系统以分区为单位来管理动态内存,而任务以内存块为单位来...
  • C语言动态内存管理及通讯录(动态版)

    千次阅读 多人点赞 2021-04-05 17:16:37
    什么是动态内存?为什么存在动态内存分配动态内存函数介绍mallocfreecallocrealloc动态版通讯录小结 什么是动态内存? 所谓动态内存分配,就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。...
  • 再议Hyper-V 动态内存管理和内存过量使用 实际操作中,慢慢成长起来的经验将会成为一份可遇而不可求的金玉。几年前,坚信虚拟化将会让我们的IT运维变得随心所欲,到现在我反而发现了这项全新业务的管理让我们常常犯...
  • C++学习笔记-DLL中动态内存管理

    千次阅读 2018-11-11 20:55:38
    动态内存管理 在dll中malloc的内存,必须在dll中free 注:这是由Windows自己的特点决定!   如果 a 编译成静态库,有下面两种解决方法: 1.b.dll 和 c.dll 使用同一个款编译器编译(保证CRT库版本一致),编译选项...
  • 单片机的动态内存管理-一以链表为例

    千次阅读 多人点赞 2016-10-13 22:44:10
    程序在运行时有时候会需要一个很大的空间去临时存储一些变量,如果一开始就分配一个很大的数组...动态内存管理就是在这样的背景下产生的,先说说编译器在编译时的内存分配,编译器在编译时会将内存分为 栈区、堆区、BSS
  • C/C++动态内存管理—(new与malloc)

    千次阅读 多人点赞 2021-03-14 20:57:43
    文章目录1.C/C++内存分布2.C语言动态内存分配2.1 malloc2.2 calloc2.3 realloc2.4 free3.C语言动态内存代码示例4.C++动态内存分配4.1 new4.1.1 operator new4.2 delete4.2.1 operator delete5.C++动态内存代码示例6....
  • C/C++动态内存管理malloc/new、free/delete的异同

    千次阅读 多人点赞 2018-07-12 20:41:17
    学习了C和C++之后,我们都知道这两种语言皆有动态内存管理,两者之间异同,我们需要系统的总结一下! 一、相同 两者都可以用来动态申请内存和释放内存; 二、不同 1.malloc/free是C/C++标准库的函数,new/...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 518,445
精华内容 207,378
关键字:

动态内存管理