内存结构-堆结构-内存分配函数
来源:互联网 发布:同程网络 编辑:程序博客网 时间:2024/03/28 20:16
内存管理(从底层到高层):
硬件层次
内存结构管理
内核层次
内存映射
堆扩展
语言层次
c::malloc
c++:new
数据结构
STL(Standard Template Library,标准模板库)
智能指针
例1
运行:编辑malloc.c
执行:gcc malloc.c -o malloc#include <stdio.h>#include <stdlib.h>main(){int *p1=malloc(4);int *p2=malloc(4);int *p3=malloc(4);int *p4=malloc(4);int *p5=malloc(4);printf("%p\n",p1);printf("%p\n",p2);printf("%p\n",p3);printf("%p\n",p4);printf("%p\n",p5);}
结果:
0x9066008
0x9066018
0x9066028
0x9066038
0x9066048
问题是:为什么开辟4字节空间,而实际上是开辟的空间间距是16字节?
尝试使用标准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;}
执行:g++ malloc.cpp -o new
结果:
0x8b53008
0x8b53018
0x8b53028
0x8b53038
0x8b53048
对比,和c的结果一模一样。
1.问题:malloc怎么分配空间?malloc月new的关系?
2.Linux对内存的结构描述
例2:
目录/proc/${pid}/ 存放进程运行时候所有的信息包括内存结构
exe 指向当前运行的程序
cwd 连接 指向当前程序所在目录
maps 保存程序运行的所有的内存结构
编辑:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>int add(int a,int b){ return a+b;}//全局区int a1 = 1; //全局变量static int a2=2;//全局静态变量const int a3=3; //全局常量main(){ int b1=4; static b2=5; const b3 =6; int *p1=malloc(4); printf("a1:%p\n",&a1); printf("a2:%p\n",&a2); printf("a3:%p\n",&a3); printf("b1:%p\n",&b1); printf("b2:%p\n",&b2); printf("b3:%p\n",&b3); printf("p1:%p\n",p1); printf("main:%p\n",&main); printf("add:%p\n",&add); printf("%d\n",getpid()); while (1);}
cd /proc/
ps aue
运行结果:
a1:0x80497e4 //全局变量--------在全局区
a2:0x80497e8 //全局静态变量--在全局区
a2:0x80497e8 //全局静态变量--在全局区
a3:0x80485f4 //全局常量--------在代码区
b1:0xbfa06c28 //局部变量--------在局部栈
b2:0x80497ec //局部静态变量--在全局区
b3:0xbfa06c24 //局部常量--------在局部栈
p1:0x84c1008 //指针--------------在堆
main:0x8048432 //在代码区
add:0x8048424 //在代码区
4710
b1:0xbfa06c28 //局部变量--------在局部栈
b2:0x80497ec //局部静态变量--在全局区
b3:0xbfa06c24 //局部常量--------在局部栈
p1:0x84c1008 //指针--------------在堆
main:0x8048432 //在代码区
add:0x8048424 //在代码区
4710
查看进程id 进入相应的文件夹 再查看maps
[sh@localhost ~]$ ll /proc/4710/cwd
lrwxrwxrwx. 1 sh SH 0 2月 28 17:53 /proc/4710/cwd -> /home/SH/project/cpp/test
[sh@localhost ~]$ ll /proc/4710/exe
lrwxrwxrwx. 1 sh SH 0 2月 28 17:53 /proc/4710/exe -> /home/SH/project/cpp/test/main
[sh@localhost ~]$ cat /proc/4710/maps
007cf000-007ed000 r-xp 00000000 fd:00 26990 /lib/ld-2.12.so
007ed000-007ee000 r--p 0001d000 fd:00 26990 /lib/ld-2.12.so
007ee000-007ef000 rw-p 0001e000 fd:00 26990 /lib/ld-2.12.so
007f9000-007fa000 r-xp 00000000 00:00 0 [vdso]
00832000-009c3000 r-xp 00000000 fd:00 26991 /lib/libc-2.12.so
009c3000-009c5000 r--p 00191000 fd:00 26991 /lib/libc-2.12.so
009c5000-009c6000 rw-p 00193000 fd:00 26991 /lib/libc-2.12.so
009c6000-009c9000 rw-p 00000000 00:00 0
08048000-08049000 r-xp 00000000 fd:00 17633 /home/SH/project/cpp/test/main 代码区,x可执行
08049000-0804a000 rw-p 00000000 fd:00 17633 /home/SH/project/cpp/test/main 全局区
084c1000-084e2000 rw-p 00000000 00:00 0 [heap]/堆
b7731000-b7732000 rw-p 00000000 00:00 0
b7743000-b7745000 rw-p 00000000 00:00 0
bf9f3000-bfa08000 rw-p 00000000 00:00 0 [stack]/栈
007ed000-007ee000 r--p 0001d000 fd:00 26990 /lib/ld-2.12.so
007ee000-007ef000 rw-p 0001e000 fd:00 26990 /lib/ld-2.12.so
007f9000-007fa000 r-xp 00000000 00:00 0 [vdso]
00832000-009c3000 r-xp 00000000 fd:00 26991 /lib/libc-2.12.so
009c3000-009c5000 r--p 00191000 fd:00 26991 /lib/libc-2.12.so
009c5000-009c6000 rw-p 00193000 fd:00 26991 /lib/libc-2.12.so
009c6000-009c9000 rw-p 00000000 00:00 0
08048000-08049000 r-xp 00000000 fd:00 17633 /home/SH/project/cpp/test/main 代码区,x可执行
08049000-0804a000 rw-p 00000000 fd:00 17633 /home/SH/project/cpp/test/main 全局区
084c1000-084e2000 rw-p 00000000 00:00 0 [heap]/堆
b7731000-b7732000 rw-p 00000000 00:00 0
b7743000-b7745000 rw-p 00000000 00:00 0
bf9f3000-bfa08000 rw-p 00000000 00:00 0 [stack]/栈
4K为1页
结论:
任何程序的内存空间分成4个基本部分
1.代码区
2.全局栈区
3.堆
4.局部栈
堆栈的区别
例3:
编辑statckleap.c
#include <stdio.h>#include <stdlib.h>#include <unistd.h>main(){ int a1=10; int a2=20; int a3=30; int *p1=malloc(4); int *p2=malloc(4); int *p3=malloc(4); printf("%p\n",&a1); printf("%p\n",&a2); printf("%p\n",&a3); printf("%p\n",p1); printf("%p\n",p2); printf("%p\n",p3); printf("%d\n",getpid()); while(1);}
结果
0xbf8bfb50|
0xbf8bfb4c | 栈相差4字节
0xbf8bfb48 |
0x8734008 |
0x8734018 | 堆相差10字节
0x8734028 |
3531
0xbf8bfb4c | 栈相差4字节
0xbf8bfb48 |
0x8734008 |
0x8734018 | 堆相差10字节
0x8734028 |
3531
查看3531进程:
005a6000-005a7000 r-xp 00000000 00:00 0 [vdso]
007cf000-007ed000 r-xp 00000000 fd:00 26990 /lib/ld-2.12.so
007ed000-007ee000 r--p 0001d000 fd:00 26990 /lib/ld-2.12.so
007ee000-007ef000 rw-p 0001e000 fd:00 26990 /lib/ld-2.12.so
00832000-009c3000 r-xp 00000000 fd:00 26991 /lib/libc-2.12.so
009c3000-009c5000 r--p 00191000 fd:00 26991 /lib/libc-2.12.so
009c5000-009c6000 rw-p 00193000 fd:00 26991 /lib/libc-2.12.so
009c6000-009c9000 rw-p 00000000 00:00 0
08048000-08049000 r-xp 00000000 fd:00 17633 /home/SH/project/cpp/test/main
08049000-0804a000 rw-p 00000000 fd:00 17633 /home/SH/project/cpp/test/main
08734000-08755000 rw-p 00000000 00:00 0 [heap]
b774e000-b774f000 rw-p 00000000 00:00 0
b7760000-b7762000 rw-p 00000000 00:00 0
bf8ad000-bf8c2000 rw-p 00000000 00:00 0 [stack]
007cf000-007ed000 r-xp 00000000 fd:00 26990 /lib/ld-2.12.so
007ed000-007ee000 r--p 0001d000 fd:00 26990 /lib/ld-2.12.so
007ee000-007ef000 rw-p 0001e000 fd:00 26990 /lib/ld-2.12.so
00832000-009c3000 r-xp 00000000 fd:00 26991 /lib/libc-2.12.so
009c3000-009c5000 r--p 00191000 fd:00 26991 /lib/libc-2.12.so
009c5000-009c6000 rw-p 00193000 fd:00 26991 /lib/libc-2.12.so
009c6000-009c9000 rw-p 00000000 00:00 0
08048000-08049000 r-xp 00000000 fd:00 17633 /home/SH/project/cpp/test/main
08049000-0804a000 rw-p 00000000 fd:00 17633 /home/SH/project/cpp/test/main
08734000-08755000 rw-p 00000000 00:00 0 [heap]
b774e000-b774f000 rw-p 00000000 00:00 0
b7760000-b7762000 rw-p 00000000 00:00 0
bf8ad000-bf8c2000 rw-p 00000000 00:00 0 [stack]
结论:
- 内存分为4个区。
- 各种变量对应存放区。
- 堆栈是一种管理内出的数据结构。
- 查看一个程序的内存地址。
3.理解malloc工作原理
例4
编辑mallocstruck.c (越界访问)
#include <stdio.h>#include <stdlib.h>main(){ int *p1=malloc(4); int *p2=malloc(4); int *p3=malloc(4); *p1=1; *(p1+1)=2; *(p1+2)=3; *(p1+3)=4; *(p1+4)=5; *(p1+5)=6; printf("%d\n",*p2); printf("%d\n",*p3);}结果是:
5
0
0
结论:
malloc使用一个数据结构(链表)来维护我们分配的空间,
连标的构成:分配的空间、上个空间数据、下个空间数据、空间大小等信息
读malloc分配的空间不要越界访问,应为容易破坏后台维护机构,导致 malloc、free、calloc、realloc不正常工作。
4.c++的new与malloc的关系
malloc new、new[]
realloc(定位分配) new()
calloc new[]
free delete、delete[]
new的实现使用malloc来实现的。
区别:new使用malloc后还要初始化空间,
基本类型,直接初始化成默认值,
UDT类型(用户自定义类型:类,结构体),调用指定的构造器
同样,delete是调用free实现。
区别:delete负责调用析构器,然后再调用free。
new 与new[ ]的区别:
new只调用一个构造器初始化。
new[ ]循环对每个区域调用构造器。
delete 月 delete[]的区别:
例子: Stu *p = new Stu[30];
delete p;调用一个析构函数,再把p指向的空间群全部释放。delete[] p;循环调用每个析构函数,再把p指向的空间群全部释放。
5.函数调用栈空间的分配与释放
5.1 总结
- 函数执行的时候有自己的临时栈空间。
- 函数的参数就在临时栈中,如果函数传递实参,则用来初始化临时参数变量。
- 通过寄存器返回值。(使用返回值返回数据)
- 通过参数返回值。(参必须是指针,指针指向的区域必须事先分配)
- 如果参数返回指针,参数就是双指针。
5.2 __stdcall __cdecl __fastcall
写在函数名前:linux:__attribute__((stdcall))
windows:__stdcall
1.决定含糊栈压栈顺序。从右到左2.决定函数栈清空方式。3.决定了函数的名字转换方式。
同样,delete是调用free实现。
0 0
- 内存结构-堆结构-内存分配函数
- 内存结构、堆结构及内存分配函数
- JVM堆内存结构分配
- linux程序的内存结构 堆结构 内存分配函数 brk/sbrk
- 结构动态内存分配
- 结构体分配内存
- JVM堆内存结构
- 结构体的内存分配
- 结构体与内存分配
- 结构体指针内存分配
- Java内存分配的结构
- 结构体的内存分配
- 结构体的内存分配
- 结构体的内存分配
- 结构体的内存分配
- 结构体的内存分配
- 结构体如何分配内存
- 结构体,联合体,内存分配
- iOS开发笔记--tableview重用问题
- 书
- 坦克大战
- Spring事务的传播行为和隔离级别
- 招聘培训之目标选才
- 内存结构-堆结构-内存分配函数
- javaSE-面向对象-异常
- JSON基础知识整理
- SSH中,不能删除数据,可以添加,修改,查找
- 算法基础(一):栈
- NStimer APIhttp://hi.baidu.com/douxinchun/item/920a7655fe7f3fd8d48bacaf
- node.js 事件乒乓
- 学生表/教师表/课程表/成绩表常见SQL查询
- eclipse4.3 安装不了m2e的egit connector的解决办法