设为首页收藏本站 |天气与日历| 2025-07-01 星期二 22:53:00 (建党节) 乙巳(蛇)年 六月初七 亥时
     
切换到窄版

私人站点

 找回密码
 立即注册
搜索
查看: 212|回复: 0

内存管理

[复制链接]

954

主题

954

帖子

3879

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3879
发表于 2022-3-8 15:20:24 | 显示全部楼层 |阅读模式
硬件层次
内存结构管理


内核层次
内存映射
堆扩展


语言层次

c:malloc  c++:new


数据结构层次
STL
智能指针


C语言:
[C++] 纯文本查看 复制代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
        int *p1=new int;
        int *p2=new int;
        int *p3=new int;
        int *p4=new int;
        int *p5=new int;
        printf("%p\n",p1);
        printf("%p\n",p2);
        printf("%p\n",p3);
        printf("%p\n",p4);
        printf("%p\n",p5);
        return 0;
}

运行结果:
[C] 纯文本查看 复制代码
root@armbain:~/code/001# ./malloc
0xb6f24150
0xb6f24160
0xb6f24170
0xb6f24180
0xb6f24190
0xb6f241a0
C++代码
[C++] 纯文本查看 复制代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
        int *p1=new int;
        int *p2=new int;
        int *p3=new int;
        int *p4=new int;
        int *p5=new int;
        printf("%p\n",p1);
        printf("%p\n",p2);
        printf("%p\n",p3);
        printf("%p\n",p4);
        printf("%p\n",p5);
        return 0;
}

运行效果
[C++] 纯文本查看 复制代码
root@armbain:~/code/001# ./malloccpp
0xb6ff4058
0xb6ff4068
0xb6ff4078
0xb6ff4088
0xb6ff4098
0xb6ff40a8
root@armbain:~/code/001#
1.问题:
malloc 是怎么分配空间的?

malloc 与new的关系?2.Linux 对内存的结构描述
1./proc/${pid}/  存放进程运行时的所有信息 包括所有信息;
cat maps;查看程序空间
空间.jpg
结论:
任何程序的空间分成4个基本部分
1.代码区
2.全局栈区
3.堆
4.局部栈
注意:ps aue 进程查看
流程.jpg

验证:
[Shell] 纯文本查看 复制代码
 /lib/ld-linux-armhf.so.3 ./while1
//同样可以执行程序

2.理解程序的变量和内存空间的关系



总结论:
1.内存分四个区
2.各种变量对于放在对应存放区
3.堆栈是一种管理内存的数据结构
4.查看程序的内存地址

3.理解malloc的工作原理

malloc 使用一个数据结构(链表)来维护分配的空间
链表的构成部分:分配的空间/上一次空间/下一个空间/空间大小
对malloc 分配的空间 不要越界访问.容易破坏后台的维护结构,
导致malloc/free/calloc/realloc 无法工作



4.c++的new 和malloc 的关系
malloc   new  new[]
realloc   new()类型;  //定位分配  /*头文件 new*/ char a[20] ; int *p=new(a) int;
calloc    new[]
free       delete delete[]
结论:
new的实现使用的是malloc 来实现的.
区别:new 使用malloc后,还要初始化空间
基本类型,直接初始化默认值.
UDT(结构体,类...)复合类型,会调用构造器

delete 调用free实现.
delete 会负责调用析构清0,然后再调用free

new 和new[]区别
new 只调用一个构造器初始化
new[] 循环对每个区域调用构造器

delete与 delete[]


5.1函数调用栈空间的分配与释放
1.函数在执行的时候,有自己的临时栈2.函数的参数就在临时栈中,如果函数传递实参,则用来初始化临时的参数变量
3.通过寄存器返回值(使用返回值,返回数据)
4.通过参数返回值.(参数必须是指针,)
           指针指向的区域,必须事先分配5.如果参数返回指针,参数就是双指针



5.2   函数的修饰属性,编译方式
[C] 纯文本查看 复制代码
//linux下 语法
 int  __attribute__((cdecl)) add(int* a, int* b);
 int  __attribute__((fastcall)) add(int* a, int* b);
 int  __attribute__((fastcall)) add(int* a, int* b);
//windows下语法
int __stdcall add(int a,int b);

__stdcall   __cdecl __fastcall
1.决定函数栈的压栈顺序
2.决定函数栈的清空方式
3.windows 环境下决定了函数的名字转换


6. far near huge 指针(windows 历史遗留问题)near 16位访问
far    32位访问
huge  综合访问




虚拟内存
问题:
           一个程序不能访问 另外一个程序指向的空间理解:
          1.每个程序的开始地址都是0x80084000
          2.程序中使用的地址不是物理地址,而是一个逻辑地址(虚拟空间)
                        逻辑地址仅仅是个编号,编号使用int 4字节整数表示                         4294967296  100000000  4096
                        每一个程序提供了4G的访问能力




问题:
        逻辑地址与物理地址关联才有意义:过程称为内存映射
背景:
        虚拟内存的提出:禁止用户字节访问物理存储
        有助于系统的稳定.
         
结论:
        虚拟地址与物理地址映射的时候有一个基本单位.
                  4K    1000   内存页
         段错误:无效访问.
         合法访问:比如malloc 分配的空间的之外的空间可以访问,但访问非法

虚拟内存的分配
           栈:编译器自动生成代码维护
           堆:地址是否映射,映射的空间是否被管理
       1.brk /sbrk(内存映射函数)


       补充:帮助手册
         man  节  关键字
         1-8   1:LINUX 系统指令(shell)
                 2:系统函数
                 3:标准C函数的文档            
                 7:系统的编程帮助           分配释放内存
                 int brk(void * end);//分配空间,释放空间
                 void *sbrk(int size); //返回空间地址

            应用:
                 1.使用sbrk分配空间
                 2.使用sbrk 得到没有映射的空间
                 3.使用brk分配空间
                 4.使用brk释放空间
           理解:
                     sbrk(int size)
                     sbrk与brk后台系统维护一个指针.
                     指针默认是NULL
                     调用sbrk,判定指针是否是0,
                            是:得到一大块空闲的首地址,同时把指针+size
                            否:返回指针,并且把指针位置+size

sbrk.png
[C++] 纯文本查看 复制代码
#include<stdio.h>
#include<unistd.h>
int find(int a) {
        if (a<=2)
        {
                return 1;
        }
        for (int i = 2; i < a; i++)
        {
                if (a%i==0)
                {
                        return 0;

                }
                return 1;

        }

}
int main() {
        
        int nums=0;
        int * ptr=sbrk(0);
        int* st_ptr = ptr;
        for (int i = 2; i < 10000; i++)
        {
                if (find(i)==1)

                { 
                        nums++;
                        ptr=sbrk(4);
                        *ptr = i;
                        printf("%d\t%p\t%d\n",nums,ptr,*ptr);
                        ptr = sbrk(0);

                        
                }

        }



        return 0;
}


总结:
智能指针
stl
new
malloc
brk/sbrk

异常处理
int brk(void *)
void *sbrk(int);
如果成功 brk 返回0     sbrk返回指针
如果失败 brk返回-1      sbrk 返回(void *)-1

unix 函数错误,修改内部变量:
errno
//////////////内存错误的几种输出
perror("");
printf("%m\n");
printf("::%s\n",strerror(errno));

字符串函数  string.h  cstring
内存管理函数  malloc memset mapcmp memcpy....
                      bzero
错误处理函数

标准IO 函数
时间函数
类型转换函数
课后练习
[C] 纯文本查看 复制代码
/*
注意事项:
通常brk和sbrk 搭配使用,
sbrk 负责分配映射内存  brk 负责偏移 和释放内存
获取10000内的兄弟素数
*/
#define _CRT_SECURE_NO_WARNINGS
#include"stdio.h"
//递归判断是不是素数
int find(int a) {
	for (int i = 2; i < a; i++)
	{
		if (a%i==0)
		{
			return a;
		}	
	}
	return 0;
}


int main(int argc, char* argv[])
{
	int* st_ptr = sbrk(0);
	int* in_ptr = st_ptr;

	//查找所有素数
	for (int i = 2; i < 10000; i++)
	{
		if (!find(i))
		{
			brk(in_ptr + 1);
			*in_ptr = i;
			in_ptr = sbrk(0);
			//printf("%p\t,%d\n", in_ptr,i);
		}

	}
	int* ptr_end = sbrk(0);
	int* temp_ptr = st_ptr;
	int* free_ptr = st_ptr;
//查找兄弟素数
	while (st_ptr != ptr_end)
	{
		if ((*(st_ptr + 1)) - (*temp_ptr) <= 2 && ((* (st_ptr + 1)) - (*temp_ptr) >0))
		{
			printf("%p\t,%d\t,%p\t,%d\n", st_ptr, *st_ptr, st_ptr+1, *(st_ptr + 1));
		}
		st_ptr++;
		temp_ptr = st_ptr;
	}
	brk(free_ptr);//free内存
	return 0;

}






回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|编程站点 ( 冀ICP备2023028127号-2 )|友链申请|

GMT+8, 2025-7-1 22:53 , Processed in 0.095621 second(s), 25 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表