堆和棧的概念區(qū)別
堆: 是大家共有的空間,分全局堆和局部堆。全局堆就是所有沒有分配的空間,局部堆就是用戶分配的空間。堆在操作系統(tǒng)對進程 初始化的時候分配,運行過程中也可以向系統(tǒng)要額外的堆,但是記得用完了要還給操作系統(tǒng),要不然就是內(nèi)存泄漏。堆里面一般 放的是靜態(tài)數(shù)據(jù),比如static的數(shù)據(jù)和字符串常量等,資源加載后一般也放在堆里面。一個進程的所有線程共有這些堆 ,所以對堆的操作要考慮同步和互斥的問題。程序里面編譯后的數(shù)據(jù)段都是堆的一部分。
棧: 是個線程獨有的,保存其運行狀態(tài)和局部自動變量的。棧在線程開始的時候初始化,每個線程的?;ハ嗒毩?,因此 ,棧是 thread safe的。每個c++對象的數(shù)據(jù)成員也存在在棧中,每個函數(shù)都有自己的棧,棧被用來在函數(shù)之間傳遞參數(shù)。操作系統(tǒng)在切換線程的時候會自動的切換棧,就是 切換ss/esp寄存器。??臻g不需要在高級語言里面顯式的分配 和釋放。支持的數(shù)據(jù)有限,一般是整數(shù),指針,浮點數(shù)等系統(tǒng)直接支持的數(shù)據(jù)類型, 并不直接支持其他的數(shù)據(jù)結(jié)構(gòu)。
預(yù)備知識—程序的內(nèi)存分配
1、棧區(qū)(stack)— 由編譯器自動分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。
2、堆區(qū)(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時可能由OS回收。注意它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事,分配方式倒是類似于鏈表。
3、全局(靜態(tài))區(qū)包含下面兩個分區(qū):
- 數(shù)據(jù)區(qū):數(shù)據(jù)段用來存放可執(zhí)行文件中已初始化全局變量,換句話說就是存放程序靜態(tài)分配的變量和全局變量。
- BSS區(qū):BSS段包含了程序中未初始化全局變量。
4、文字常量區(qū) —常量字符串就是放在這里的。程序結(jié)束后由系統(tǒng)釋放。
5、程序代碼區(qū)—存放函數(shù)體的二進制代碼。

關(guān)于字符串
/*
static與const組合:在每個文件都需要定義一份靜態(tài)全局變量。
extern與const組合:只需要定義一份全局變量,多個文件共享。
static和extern定義的變量都在全局(靜態(tài))區(qū)
*/
//靜態(tài)變量
static LMClass *obj4 ;
//全局靜態(tài)變量
//extern作用:只是用來獲取全局變量(包括全局靜態(tài)變量)的值,不能用于定義變量
extern NSString *externString = @"dddd";
int myInt = 20;//全局初始化區(qū)(數(shù)據(jù)區(qū))
NSString *str;//全局未初始化區(qū)(BSS區(qū))
-(void) testString{
NSString *string = @"dddd";
NSLog(@"dddd -> %p",@"dddd"); //dddd是常量字符串,存在常量區(qū)
NSLog(@"string->%p",string); //string指針存在棧區(qū), 指針指向常量區(qū)
NSLog(@"Int -> %u",0xa5a5a5a5);
//string2在棧中,指向堆區(qū)的地址
NSString *string2 = [[NSString alloc] initWithFormat:@"dddd"];
NSLog(@"string2-> %p",string2);
NSString *string3 = [NSString stringWithFormat:@"dddd"];
NSLog(@"string3 -> %p", string3);
// string3 = nil;
NSLog(@"string3 -> %p", string3);
//string2 和 string3 都是指向同一地址
// string2 = nil;
NSString *string4 = [string3 copy];
//string4 也和 string2,3地址一樣
NSLog(@"string4 -> %p", string4);
//externString是指向常量區(qū)
NSLog(@"externString ->%p", externString);
}
dddd -> 0x104420b70 string->0x104420b70 Int -> 2779096485 string2-> 0xa000000646464644 string3 -> 0xa000000646464644 string3 -> 0xa000000646464644 string4 -> 0xa000000646464644 externString ->0x10ecfab70
這圖片是在當(dāng)前控制器po的

這個我在沒有創(chuàng)建上面的控制器時po的。

0xa000000646464644po出也是dddd。
所以我的理解是string2,3,4的指向堆區(qū),因為字符串存在常量區(qū),所以它們都是指向常量區(qū)的字符串。
但是為什么我打印的常量dddd -> 0x104420b70,和string2,3,4的0xa000000646464644不一樣。希望有大神能告訴我一下。
關(guān)于對象
-(void) testObject{
//對象的創(chuàng)建都是存放在堆區(qū)中,如果是局部變量,因為ARC的存在,所以不用程序員再手動釋放,過了作用域obj1,2,3指向的內(nèi)存都會被釋放。
LMClass *obj1 = [[LMClass alloc] init];
NSLog(@"obj1->%p-----obj1指針%p",obj1, &obj1);
LMClass *obj2 = [[LMClass alloc] init];
NSLog(@"obj2->%p-----obj2指針%p",obj2, &obj2);
LMClass *obj3 = [obj2 copy];
NSLog(@"obj3->%p-----obj3指針%p",obj3, &obj3);
//obj2釋放了,原來obj2指向的內(nèi)存成為空閑內(nèi)存
obj2 = nil;
}
打印數(shù)據(jù)
obj1->0x6100000148b0-----obj1指針0x7fff57aecc18
obj2->0x618000014b30-----obj2指針0x7fff57aecc10
obj3->0x600000014b80-----obj3指針0x7fff57aecc08
(lldb) po obj2
nil
(lldb) po 0x618000014b30
107202383792720 //對象原來的地址釋放掉
(lldb) po &obj2
0x00007fff57aecc10