关于堆栈的讲解(一)
1、 堆和栈基本概念: (来自网上)
简单的来讲堆(heap)上分配的内存,系统不释放,而且是动态分配的。
栈(stack)上分配的内存系统会自动释放,它是静态分配的。栈的分配是从内存的高地址向低地址分配的,而堆则相反(好像这里说错了,堆本来就是 链式存储,哪里来的高到低,低到高)。12:33:14 对的,链表本来就是由 低地址 向 高地址 遍历。。
由malloc或new分配的内存都是从heap(堆)上分配的内存,从heap(堆)上分配的内存必须有程序员自己释放,用free来释放,否则这块内存会一直被占用而得不到释放,就出现了“内存泄露(Memory Leak)”。
这样会造成系统的可分配内存的越来越少,导致系统崩溃。(可以写恶意程序,让系统崩溃吧^*^)
2、预备知识
一个由c/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放,放在代码段
5、程序代码区—存放函数体的二进制代码。
1、
#include<stdio.h>
#include<string.h>
#include<malloc.h>
int a = 0; //全局初始化区
char *p1; //全局未初始化区 0x0000 0000 在 BSS 段
main()
{
int b=3; // 栈 显然在 栈 ,存放局部变量的值
char s[] = "abc "; //栈地址 也是局部变量 ,只不过是数组
char *p2; //栈 P2地址是 0x12ff70,说明是对的
char *p3 = "123456 "; //123456/0在常量区,p3在栈上,地址是 0x12ff6c,但是 123456 是放在常量区的 ,所以说和 上面的数组s[]还是有一点区别的,数组里面放在 栈区 , 指针指向的 放在常量区(不能理解的是 这里的常量区究竟是 代码段还是 数据段)
我的理解是在 代码段吧!!网上说(在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。)
所以我们来验证了一下,令 *(p+1)='4' 也就是打算 把 ‘123456’中的 2 改为 '4',然后如下图,所以说 不能 写,所以说 是常量在 代码段,也不可以写。
static int c =0; //全局(静态)初始化区
p1 = (char *)malloc(10); // 放在了 堆区
p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456 "); //123456/0放在常量区,编译器可能会将它与p3所指向的 "123456 "优化成一个地方。
}
好难,自己理解吧!!!!
常量区 文本段 代码段 | 堆区 | 全局静态区(也叫数据段) | 栈 | ||||||||
都说代码段不可写,但我 | |||||||||||
感觉可以写啊??why | c 0x004225a0 | ||||||||||
这里你理解错了,这里可以叫 | |||||||||||
代码段 又可以叫 文本段,这得看自己怎么定义 | 开始的 &p1 0x4225a4 | B0 | p3 0x0012ff6c | 1c | |||||||
比如: AREA RESET, CODE, READONLY |
1c | 它指向的 123456 在常量区 | f0 | ||||||||
AREA伪指令用于定义一个代码段在这里,自然只读 | 43 | 41 | |||||||||
如果定义数据段,就可以修改了,有没有 const | p2 0x00431c70 | 00 | 00 | ||||||||
0x0041f01c | 31 ' 1 ' | p2 0x0012ff70 | cc | ||||||||
32 '2' | cc | ||||||||||
33 3 | cc | ||||||||||
34 4 | cc | ||||||||||
35 5 | s 0x0012ff74 | 61 a | |||||||||
36 6 | 62 b | ||||||||||
这里是用了 strcpy | 63 c | ||||||||||
p1 0x00431cb0 存放 '123456' | 20 空格 | ||||||||||
00 '\0' | |||||||||||
cc | |||||||||||
cc | |||||||||||
cc | |||||||||||
b 0x0012ff7c | 03 | ||||||||||
应为是 int 占 四个字节 | 00 | ||||||||||
00 | |||||||||||
00 |
你懂了吗? 由于 p1 p2 在堆里面,所以 最后添加 free(p1), free(p2) ,释放它的内存。
还有疑问: 为什么 是 0x12ff74 而不是 0x12ff78 ,很纠结,还望大神能够指教。78坑定不行的,放不下,好像计算机讲 要 对齐 什么的,不太懂唉,就这样吧,有大神讲讲啊。求助
疑问
p1 = (char *)malloc(10); // 放在了 堆区 p1 0x00431cb0
p2 = (char *)malloc(20); // 也放在了 堆区 ,不是说 堆区应该由 低地址向高地址来链式存储吗 。 p2 0x00431c70 , 不是应该 p1 在低位的么??? why
2、 第二个 问题 比较