为C++标准库容器写自己的内存分配程序
- 格式:doc
- 大小:40.00 KB
- 文档页数:8
malloc内存分配流程在编程中,动态内存分配是一种常见的操作,而malloc()函数是用于在运行时分配内存的标准C库函数之一。
下面是malloc内存分配的流程。
1. 引入头文件:在使用malloc函数之前,需要在代码的开头引入头文件<cstdlib>或<stdlib.h>,以便使用malloc函数的定义和相关函数。
2. 了解malloc函数的作用:malloc函数用于在堆内存中动态分配指定字节数的内存空间,并返回一个指向分配内存开始位置的指针。
3. 为内存分配指定字节数:在调用malloc函数时,需要指定需要分配的内存空间的字节数,以便函数能够为该内存空间分配足够的大小。
例如,如果需要分配10个int类型的元素,可以使用sizeof(int) * 10来指定所需的字节数。
4. 检查分配是否成功:在调用malloc函数后,需要检查分配是否成功。
当分配成功时,malloc函数返回一个非空指针,该指针指向分配的内存空间的开始位置;当分配失败时,malloc函数返回一个空指针NULL。
5. 使用分配的内存空间:一旦分配成功,可以使用返回的指针来操作分配的内存空间。
例如,可以对分配的内存空间进行读写操作,存储数据或者访问已存储的数据。
6. 释放已分配的内存空间:在使用完分配的内存空间后,为了避免内存泄漏,应该使用free函数将其释放。
通过调用free函数,并将分配的指针作为参数传入,释放的内存将返回给系统,可以再次用于其他任务。
总结:将malloc内存分配的流程概括起来,首先引入头文件,然后了解malloc函数的作用,指定所需分配的字节数,检查分配是否成功,对分配的内存空间进行操作,最后使用free函数释放已分配的内存空间。
这个流程在动态内存分配中有着广泛的应用,能够帮助程序实现灵活的内存管理。
C#之内存分配在C#中,内存分成5个区,他们分别是堆、栈、⾃由存储区、全局/静态存储区和常量存储区。
栈,就是那些由编译器在需要的时候分配,在不需要的时候⾃动清楚的变量的存储区。
⾥⾯的变量通常是局部变量、函数参数等。
堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应⽤程序去控制,⼀般⼀个new就要对应⼀个delete。
如果程序员没有释放掉,那么在程序结束后,操作系统会⾃动回收。
⾃由存储区,就是那些由malloc等分配的内存块,他和堆是⼗分相似的,不过它是⽤free来结束⾃⼰的⽣命的。
全局/静态存储区,全局变量和静态变量被分配到同⼀块内存中,在以前的C语⾔中,全局变量⼜分为初始化的和未初始化的,在C++⾥⾯没有这个区分了,他们共同占⽤同⼀块内存区。
常量存储区,这是⼀块⽐较特殊的存储区,他们⾥⾯存放的是常量,不允许修改(当然,你要通过⾮正当⼿段也可以修改,⽽且⽅法很多)明确区分堆与栈在bbs上,堆与栈的区分问题,似乎是⼀个永恒的话题,由此可见,初学者对此往往是混淆不清的,所以我决定拿他第⼀个开⼑。
⾸先,我们举⼀个例⼦:void f() { int* p=new int[5]; }这条短短的⼀句话就包含了堆与栈,看到new,我们⾸先就应该想到,我们分配了⼀块堆内存,那么指针p呢?他分配的是⼀块栈内存,所以这句话的意思就是:在栈内存中存放了⼀个指向⼀块堆内存的指针p。
在程序会先确定在堆中分配内存的⼤⼩,然后调⽤operator new分配内存,然后返回这块内存的⾸地址,放⼊栈中,他在VC6下的汇编代码如下:00401028 push 14h0040102A call operator new (00401060)0040102F add esp,400401032 mov dword ptr [ebp-8],eax00401035 mov eax,dword ptr [ebp-8]00401038 mov dword ptr [ebp-4],eax这⾥,我们为了简单并没有释放内存,那么该怎么去释放呢?是delete p么?澳,错了,应该是delete []p,这是为了告诉编译器:我删除的是⼀个数组,VC6就会根据相应的Cookie信息去进⾏释放内存的⼯作。
第1篇一、实验目的1. 理解操作系统内存分配的基本原理和常用算法。
2. 掌握动态分区分配方式中的数据结构和分配算法。
3. 通过编写程序,实现内存分配和回收功能。
二、实验环境1. 操作系统:Linux2. 编程语言:C语言3. 开发工具:GCC编译器三、实验原理1. 内存分配的基本原理操作系统内存分配是指操作系统根据程序运行需要,将物理内存分配给程序使用的过程。
内存分配算法主要包括以下几种:(1)首次适应算法(First Fit):从内存空间首部开始查找,找到第一个满足条件的空闲区域进行分配。
(2)最佳适应算法(Best Fit):在所有满足条件的空闲区域中,选择最小的空闲区域进行分配。
(3)最坏适应算法(Worst Fit):在所有满足条件的空闲区域中,选择最大的空闲区域进行分配。
2. 动态分区分配方式动态分区分配方式是指操作系统在程序运行过程中,根据需要动态地分配和回收内存空间。
动态分区分配方式包括以下几种:(1)固定分区分配:将内存划分为若干个固定大小的分区,程序运行时按需分配分区。
(2)可变分区分配:根据程序大小动态分配分区,分区大小可变。
(3)分页分配:将内存划分为若干个固定大小的页,程序运行时按需分配页。
四、实验内容1. 实现首次适应算法(1)创建空闲分区链表,记录空闲分区信息,包括分区起始地址、分区大小等。
(2)编写分配函数,实现首次适应算法,根据程序大小查找空闲分区,分配内存。
(3)编写回收函数,回收程序所占用的内存空间,更新空闲分区链表。
2. 实现最佳适应算法(1)创建空闲分区链表,记录空闲分区信息。
(2)编写分配函数,实现最佳适应算法,根据程序大小查找最佳空闲分区,分配内存。
(3)编写回收函数,回收程序所占用的内存空间,更新空闲分区链表。
3. 实验结果分析(1)通过实验,验证首次适应算法和最佳适应算法的正确性。
(2)对比两种算法在内存分配效率、外部碎片等方面的差异。
五、实验步骤1. 创建一个动态内存分配模拟程序,包括空闲分区链表、分配函数和回收函数。
c语言cpu分配内存的原则:
以下是一些关于C语言中内存分配的原则:
1.静态存储区:这部分内存是在程序编译时分配的,包括全局变量和静态变量。
这些
变量的生命周期是整个程序的执行期间。
2.栈内存:这部分内存是在程序执行期间动态分配的,主要用来存储函数调用的局部
变量和函数参数。
当函数执行结束时,这部分内存会自动释放。
3.堆内存:这是动态内存分配区域,通过malloc,calloc等函数分配。
当不再需要这部
分内存时,应使用free函数释放。
需要注意的是,如果不正确地使用这些函数(例如,试图释放同一块内存两次或者在释放内存后继续使用它),可能会导致程序崩溃或未定义的行为。
4.代码段:也称为文本段,这是用来存储程序的二进制代码的区域。
这部分内存通常
不可写,因为它是只读的,以防止程序意外地修改其指令。
5.运行时内存分配:C语言标准库提供了一些函数用于在运行时动态分配和释放内存,
如malloc()、calloc()、realloc()和free()。
这些函数允许程序员在运行时分配和释放内存,这在处理大量数据或需要根据程序运行情况动态调整数据结构大小时非常有用。
内存分配方式范文内存分配是计算机中的重要概念,它指的是将计算机的内存资源分配给不同的程序和数据。
内存分配方式可以根据分配的策略和实现方式来进行分类。
下面将介绍几种常见的内存分配方式。
1.静态分配:静态分配是指在编译或链接阶段将内存空间分配给程序的变量或数据结构。
在静态分配中,内存的分配和释放是由编译器或链接器完成的,程序在运行期间不会改变内存分配的情况。
静态分配的优点是分配速度快,不会发生内存碎片问题,但缺点是需要预先确定内存的大小,不能动态调整。
2.动态分配:动态分配是在程序运行期间根据需要分配和释放内存空间。
常见的动态分配方式有以下几种:- 堆(Heap)分配:堆分配是通过指定大小在堆内存中分配一块连续的内存空间。
它通常用于创建动态分配的数据结构,如链表、树、堆等。
堆分配的优点是可以根据需要分配灵活大小的内存,但缺点是分配和释放的速度较慢,并且容易产生内存碎片。
- 栈(Stack)分配:栈分配是指在程序运行期间分配局部变量和函数调用的内存空间。
栈内存具有后进先出的特性,每次分配内存只需要修改栈指针即可。
栈分配的优点是分配和释放速度快,但缺点是分配的内存大小固定,不适合动态分配。
- 池(Pool)分配:池分配是指事先在内存中创建一定数量的内存块,然后根据需要从池中分配和释放内存。
池分配的优点是分配和释放速度快,且不容易产生内存碎片,但缺点是需要事先确定池的大小,不能动态调整。
3.分区分配:分区分配是指将内存空间分成多个固定大小的分区,每个分区用于分配给不同的程序或数据。
常见的分区分配方式有以下几种:-等大小分区:等大小分区是将内存空间分成大小相等的分区,每个分区只能分配给一个程序或数据。
这种分区方式容易产生内存碎片,但分配和释放速度较快。
-不等大小分区:不等大小分区是将内存空间分成大小不等的分区,每个分区可以根据需要分配给不同大小的程序或数据。
这种分区方式可以更有效地利用内存空间,但分配和释放速度较慢。
c中内存分配与释放(malloc,realloc,calloc,free)函数内容的整理malloc:原型:extern void *malloc(unsigned int num_bytes); 头文件:在TC2.0中可以用malloc.h 或alloc.h (注意:alloc.h 与malloc.h 的内容是完全一致的),而在V isual C++6.0中可以用malloc.h或者stdlib.h。
功能:分配长度为num_bytes字节的内存块返回值:如果分配成功则返回指向被分配内存的指针(此存储区中的初始值不确定),否则返回空指针NULL。
当内存不再使用时,应使用free()函数将内存块释放。
函数返回的指针一定要适当对齐,使其可以用于任何数据对象。
说明:关于该函数的原型,在旧的版本中malloc 返回的是char型指针,新的ANSIC标准规定,该函数返回为void型指针,因此必要时要进行类型转换。
名称解释:malloc的全称是memory allocation,中文叫动态内存分配。
函数声明void *malloc(size_t size); 说明:malloc 向系统申请分配指定size个字节的内存空间。
返回类型是void* 类型。
void* 表示未确定类型的指针。
C,C++规定,void* 类型可以强制转换为任何其它类型的指针。
备注:void* 表示未确定类型的指针,更明确的说是指申请内存空间时还不知道用户是用这段空间来存储什么类型的数据(比如是char还是int或者...)从函数声明上可以看出。
malloc 和new 至少有两个不同: new 返回指定类型的指针,并且可以自动计算所需要大小。
比如:int *p; p = new int; //返回类型为int* 类型(整数型指针),分配大小为sizeof(int); 或:int* parr; parr = new int [100]; //返回类型为int* 类型(整数型指针),分配大小为sizeof(int) * 100; 而malloc 则必须要由我们计算字节数,并且在返回后强行转换为实际类型的指针。
分配内存函数
分配内存函数是指在程序中动态地分配内存空间的函数。
在C语
言中,常用的分配内存函数有malloc、calloc、realloc等。
1. malloc函数:malloc函数的原型为void *malloc(size_t size),功能是分配size字节的内存空间,并返回该空间的起始地址。
这个函数不会对申请到的空间进行初始化。
2. calloc函数:calloc函数的原型为void *calloc(size_t nmemb, size_t size),功能是分配nmemb个元素,每个元素大小为
size字节的内存空间,并返回该空间的起始地址。
这个函数会将申请
到的空间全部初始化为0。
3. realloc函数:realloc函数的原型为void *realloc(void
*ptr, size_t size),功能是重新分配ptr指向的内存空间的大小为size字节,并返回新的空间起始地址。
如果ptr指向的空间大小不够,会开辟新的空间并将数据复制到新的空间中,如果大小足够则直接返
回原空间的地址,如果size为0则释放空间并返回NULL。
这些函数在申请内存空间时都可能导致内存分配失败,因此需要
用if判断申请空间是否成功。
例如:
```
int *p = (int*)malloc(sizeof(int)*n);
if(p == NULL){
printf("分配内存失败");
exit(1);
}
```。
c++内存分配函数malloca/alloca:内存分配函数,与malloc,calloc,realloc类似。
但是注意⼀个重要的区别,_alloca是在栈(stack)上申请空间,⽤完马上就释放。
alloca包含在头⽂件malloc.h中,在某些系统中会宏定义成_alloca使⽤。
注意:注意它分配的内存会⾃动释放。
也就是说, ⽤alloca 分配的内存在栈上分配的内存在栈上。
所以释放不需 1.在调⽤alloca的函数返回的时候, 它分配的内存会⾃动释放要⽤户使⽤free。
2.alloca不具可移植性, ⽽且在没有传统堆栈的机器上很难实现。
当它的返回值直接传⼊另⼀个函数时会带来问题,因为他分配在栈上. 总结:由于这些原因, alloca不宜使⽤在必须⼴泛移植的程序中, 不管它可能多么有⽤。
realloc:原来的指向的内存指针⽆变化,并返回NULL;如重新分配内存并返回void类型, 如果没有⾜够的内存扩展内存块,则原来的指向的内存指针⽆变化,重新分配⼤⼩设为0,⽽释放原来的内存块,并返回NULL。
果重新分配⼤⼩设为calloc:分配指定数⽬的元素,每个元素的⼤⼩由size指定, 并将其初始化为0, calloc调⽤malloc使⽤C++ _set_new_mode函数来设置新的处理⽅式, 默认情况下,malloc 失败时不调⽤分配内存的处理程序例程。
失败时不调⽤分配内存的处理程序例程。
malloc:从堆上分配指定⼤⼩的字节数并返回void类型,如分配失败则返回NULL,malloc分配的字节数可能⽐指定的字节要,因此malloc分配的内存也不能跨进程调⽤。
函数,多,这是由内存对齐⽅式决定的, malloc实际上调⽤了HeapAlloc函数new:分配内存的对象或数组类型的对象和返回⼀个适当类型,并调⽤对象的构造函数及在delete时调⽤对象的析构函数。
其实现基于malloc调⽤。
下⾯是windows系统提供的API函数:1. VirtualAlloc/VirtualAllocEx在虚拟地址空间中保留或提交内存, 每次操作⼤⼩为Page页⼤⼩(windows⼀般为4K)的整数倍, 因此需要⾃⼰计算内存分配算法(可以使⽤HeapAlloc或GlobalAlloc由系统⾃动分配计算), 在没有使⽤MEM_RESET的情况下会初始化内存块(0), VirtualAllocEx还可以在其他进程中的保留内存操作,并使⽤其对应的VirtualFree/VirtualFreeEx释放内存2. HeapAlloc/HeapFree在指定的Heap中分配内存,heap应该由CreateHeap或GetProcessHeap返回,分配的内存不能移动,CreateHeap 创建的堆只能在调⽤的进程中使⽤,因此如需跨进程调⽤不能使⽤此种分配⽅式,由HeapFree释放.3. GlobalAlloc/GlobalFree从全局堆分配指定字节的内存,分配的内存可跨进程访问,并使⽤8字节对齐⽅式,由GlobalFree释放,在使⽤GlobalAlloc分配的内存块时需调⽤GlobalLock和GlobalUnlock函数。
c语言动态分配内存函数C语言是一门很古老但依然强大的编程语言,作为一门底层语言,C语言与内存密不可分。
在C语言中,内存分配是一个非常重要的概念。
C语言提供了很多函数来进行内存管理,其中最为常用的便是动态分配内存函数。
本文将围绕动态分配内存函数来进行分步介绍。
1. malloc函数malloc函数是C语言中最为基本的动态分配内存函数,该函数会在堆内存中分配一块指定大小的内存块,并返回该内存块的首地址。
下面是malloc函数的基本语法:void* malloc(unsigned int size);其中,size参数表示要分配的内存块的大小,函数返回一个void型指针,该指针指向已分配的内存块的首地址。
使用malloc函数的方法如下所示:int* arr = (int*)malloc(sizeof(int) * 10);该语句将在堆内存中分配一块大小为40字节(即10个int型变量所占用的内存)的内存块,并将arr指针指向该内存块的首地址。
2. calloc函数calloc函数与malloc函数类似,也是用于动态分配内存的函数。
但与malloc函数不同的是,calloc函数还会对分配的内存块进行初始化。
同时,calloc函数的语法也略有不同:void* calloc(unsigned int num, unsigned int size);其中,num参数表示要分配的内存块的数量,size参数则表示每个内存块的大小。
使用calloc函数的方式如下所示:int* arr = (int*)calloc(10, sizeof(int));该语句将在堆内存中分配一块大小为40字节(即10个int型变量所占用的内存)的内存块,并将该内存块中每个字节都初始化为0,并将arr指针指向该内存块的首地址。
3. realloc函数realloc函数是用于重新分配已经分配的内存块的函数。
该函数接受两个参数,第一个参数是原内存块的地址,第二个参数是新的内存块大小。
C语言分配内存并赋值的函数1. 概述在C语言中,我们经常需要动态地分配内存来存储数据。
为了方便地进行内存分配和赋值操作,C语言提供了一些特定的函数。
这些函数可以帮助我们在程序运行时动态地分配内存,并将指定的值赋给所分配的内存空间。
本文将详细介绍C语言中的几个常用的分配内存并赋值的函数,包括malloc、calloc和realloc。
我们将分别介绍它们的定义、用途和工作方式,并给出一些示例代码来说明它们的使用方法。
2. malloc函数2.1 定义malloc函数是C语言中用于动态分配内存的函数。
它的原型定义在stdlib.h头文件中,其定义如下:void* malloc(size_t size);2.2 用途malloc函数用于在程序运行时动态地分配指定大小的内存空间。
这个函数返回一个指向分配内存的指针,如果分配失败则返回NULL。
2.3 工作方式malloc函数的工作方式如下:1.接收一个size_t类型的参数size,表示需要分配的内存空间的大小。
2.在堆(heap)中分配一块大小为size的连续内存空间。
3.返回指向分配内存的指针,如果分配失败则返回NULL。
2.4 示例代码下面是一个使用malloc函数分配内存并赋值的示例代码:#include <stdio.h>#include <stdlib.h>int main() {int* ptr;int size = 5;ptr = (int*)malloc(size * sizeof(int));if (ptr == NULL) {printf("内存分配失败\n");return 1;}for (int i = 0; i < size; i++) {ptr[i] = i + 1;}for (int i = 0; i < size; i++) {printf("%d ", ptr[i]);}free(ptr);return 0;}上述代码中,我们使用malloc函数分配了一块大小为 5 * sizeof(int)的内存空间,并将其地址赋给指针ptr。
为C++标准库容器写自己的内存分配程序根据sgi 的STL源码的二级分配算法改写的内存池分配程序,只要稍微修改就可以实现共享内存方式管理,使用C++标准库容器中的map,set,multimap,multiset测试通过,vector测试通不过,原因是在内存回收的时候考虑的比较简单,vector每次分配内存个数不固定,回收也不固定,这样的话,程序还需要继续完善。
内存池管理程序源码如下:以下是引用片段:#ifndef MY_ALLOCATOR_H_#define MY_ALLOCATOR_H_#include "stdafx.h"#include#includenamespace happyever{enum { NODENUMS = 2 };union _Obj{union _Obj* M_free_list_link;char M_client_data[1];} ;typedef union _Obj Obj;struct _Cookie{int iShmKey; /* 共享内存键值 */int iShmID; /* iShmKey对应的shmid */int iSemKey; /* 锁信号键值 */int iSemID; /* 锁信号标识 */int iTotalsize; /* 容器总容量 */void* pStartall; /* 共享内存自身地址 */ char* pStartfree; /* 自由空间的开始地址*/ char* pEndfree; /* 自由空间的结束地址*/ int iUseNum[NODENUMS];/*用来存放free_list中节点的size*/short sFreelistIndex[NODENUMS];/*存放分配内存节点的链表*/Obj* uFreelist[NODENUMS];};typedef struct _Cookie Cookie;//Obj;//Cookie;static Cookie *pHead = NULL;templateclass MyAlloc{private:static const int ALIGN = sizeof(Obj);int round_up(int bytes);int freelist_index(int bytes);int freelist_getindex(int bytes);char* chunk_alloc(int size, int *nobjs); void* refill(int num,int n);public:// type definitionstypedef T value_type;typedef T* pointer;typedef const T* const_pointer;typedef T& reference;typedef const T& const_reference;typedef std::size_t size_type;typedef std::ptrdiff_t difference_type;templatestruct rebind{typedef MyAlloc other;};pointer address (reference value) const{return &value;}const_pointer address (const_reference value) const {return &value;}MyAlloc() throw(){std::cout<<"MyAlloc"<}MyAlloc(const MyAlloc& x) throw(){std::cout<<"const MyAlloc"<}templateMyAlloc (const MyAlloc& x) throw(){std::cout<<"const MyAlloc"<}~MyAlloc() throw()std::cout<<"~MyAlloc"<}size_type max_size () const throw(){return std::numeric_limits::max() / sizeof(T);}//void PrintFreelistAndCookie();pointer allocate (size_type num, const void* = 0) {pointer ret = 0;Obj** my_free_list;Obj* result;int index;// print message and allocate memory with global new std::cerr << "allocate " << num << " element(s)"<< " of size " << sizeof(T) << std::endl;index = freelist_index(sizeof(T));if(index >= NODENUMS){return NULL;}my_free_list = pHead->uFreelist + index;//Lock(semid,LOCK_NUM);result = *my_free_list;if (result == 0){ret = (pointer)refill((int)num, round_up(sizeof(T))); }else*my_free_list = result->M_free_list_link;ret = (pointer)result;}//UnLock(semid,LOCK_NUM);pHead->iUseNum[index] = pHead->iUseNum[index] + (int)num; if(0 == ret){std::cerr << "alloc memory fail!" << std::endl;exit(1);}std::cerr << " allocated at: " << (void*)ret << std::endl; PrintFreelistAndCookie();return ret;}void construct (pointer p, const T& value){// initialize memory with placement newnew((void*)p)T(value);}void destroy (pointer p){// destroy objects by calling their destructorp->~T();}void deallocate (pointer p, size_type num){Obj** my_free_list;Obj* q ;int index;index = freelist_getindex(sizeof(T));if(index >= NODENUMS){std::cerr << "deallocate memory fail!" << std::endl;exit(1);}my_free_list = pHead->uFreelist + index;q = (Obj*) p;//Lock(semid,LOCK_NUM);/*这个地方可能会有问题*///for(int i=0 ;i{q->M_free_list_link = *my_free_list;*my_free_list = q;}//UnLock(semid,LOCK_NUM);pHead->iUseNum[index] = pHead->iUseNum[index] - (int)num;std::cerr << "deallocate " << num << " element(s)"<< " of size " << sizeof(T)<< " at: " << (void*)p << std::endl; PrintFreelistAndCookie();}};templateint MyAlloc::round_up(int bytes){int i;i = bytes;if(bytes < ALIGN){i = ALIGN;}std::cout<<"round_up:bytes="<<bytes<<" , return="<<i< return i;};templateint MyAlloc::freelist_index(int bytes){int i;for(i=0 ; i< NODENUMS ; i++){if(pHead->sFreelistIndex[i] == bytes)break;。