目录
内存分布
一 内存分布图如下
二 分段说明
text段:
代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。
这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读(某些架构也允许代码段为可写,即允许修改程序)。
data段:
数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。
数据段属于静态内存分配。
bss段:
bss段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。
bss是英文Block Started by Symbol的简称。
bss段属于静态内存分配。
堆(heap):
堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。
当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);
当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)
栈(stack):
是用户存放程序临时创建的局部变量,
也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。
除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中
三 注意
1 text和data段都在可执行文件中(在嵌入式系统里一般是固化在镜像文件中),由系统从可执行文件中加载;
2 bss段不在可执行文件中,由系统初始化,清0操作。
3 包含data段和bss段的整个区段此时通常称为数据区
//代码片段一
int ar[30000];
void main(){
......
}
//代码片段二
int ar[300000] = {1, 2, 3, 4, 5, 6 };
void main(){
......
}
片段二的可执行文件远远大于片段一的可执行文件
代码演示
int a = 1;
- (IBAction)memoryLayout:(id)sender {
//常量区(.data)
//a: 0x100fdb4dc 1
NSLog(@"a: %p %d",&a,a);
}
- (IBAction)memoryLayout1:(id)sender {
//常量区(.data)
//b: 0x100fdb4e0 2
static int b = 2;
NSLog(@"b: %p %d",&b,b);
b = 3;
}
int c;
- (IBAction)memoryLayout2:(id)sender {
//静态区(.bss)
//c: 0x102bee154 0
NSLog(@"c: %p %d",&c,c);
}
- (IBAction)memoryLayout3:(id)sender {
//静态区(.bss)
//d: 0x102beb858 0
static int d;
NSLog(@"d: %p %d",&d,d);
}
- (IBAction)memoryLayout4:(id)sender {
//变量e 常量区(.data)
//字符串 常量区(.data)
//e: 0x1044bf508 0x1044625f0
static NSString * e = @"abcdefghijklmnopqrstuvw";
NSLog(@"e: %p %p",&e,e);
//变量f 栈区(.stack)
//字符串 常量区(.data)
//f: 0x16bd2cf50 0x1044625f0
NSString * f = @"abcdefghijklmnopqrstuvw";
NSLog(@"f: %p %p",&f,f);
//变量g 栈区(.stack)
//字符串 常量区(.data)
//g: 0x16bd2cf48 0x1044625f0
NSString * g = [[NSString alloc]
initWithString:@"abcdefghijklmnopqrstuvw"];
NSLog(@"g: %p %p",&g,g);
//变量h 栈区(.stack)
//字符串 堆区(.heap)
//h: 0x16bd2cf40 0x281afb720
NSString * h = [[NSString alloc]
initWithFormat:@"%@",@"abcdefghijklmnopqrstuvw"];
NSLog(@"h: %p %p",&h,h);
}
关于static的的演示
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
static int memoryNum = 100;
@interface MemoryObject : NSObject
- (void)testOne;
- (void)testTwo;
@end
NS_ASSUME_NONNULL_END
#import "MemoryObject.h"
@implementation MemoryObject
- (void)testOne {
memoryNum++;
NSLog(@"testOne:memoryNum %d",memoryNum);
}
- (void)testTwo {
memoryNum++;
NSLog(@"testTwo:memoryNum %d",memoryNum);
}
@end
#import "MemoryObject.h"
NS_ASSUME_NONNULL_BEGIN
@interface MemoryObject (one)
- (void)testThree;
@end
NS_ASSUME_NONNULL_END
#import "MemoryObject+one.h"
@implementation MemoryObject (one)
- (void)testThree {
memoryNum++;
NSLog(@"testThree:memoryNum %d",memoryNum);
}
@end
- (IBAction)memoryLayout5:(id)sender {
NSLog(@"外部:memoryNum %d",memoryNum);//外部:memoryNum 100
memoryNum = 1000;
NSLog(@"外部:memoryNum %d",memoryNum);//外部:memoryNum 1000
MemoryObject * obj = [[MemoryObject alloc] init];
[obj testOne];//testOne:memoryNum 101
[obj testTwo];//testTwo:memoryNum 102
NSLog(@"外部:memoryNum %d",memoryNum);//外部:memoryNum 1000
[obj testThree];//testThree:memoryNum 101
NSLog(@"外部:memoryNum %d",memoryNum);//外部:memoryNum 1000
}
行者常至,为者常成!