上次分享整理的面試知識點 I , 今天咱們來繼續分享面試知識點整理 IIlinux
linux kernel 內核空間、內存管理、進程管理設備、驅動虛擬文件系統(vfs) | 內核空間是受保護的,用戶不能對內核空間讀寫,不然會出現段錯誤 |
---|---|
環境變量(env) | PATH |
命令行參數 | char *agrv[] |
棧區⬇️ | 函數的返回地址,返回值,參數,局部變量 |
共享庫(映射區)⬇️ | 調用動態庫,或者mmap函數進行文件映射 |
堆區⬆️ | 用new/malloc申請的內存,同時須要適用delete/free來釋放採用鏈式儲存結構 |
.bss區 | 未初始化的全局變量和靜態變量以及 初始化爲 0 的 全局變量和靜態變量編譯時就已經分配了空間 |
.data區 | 已初始化的全局變量和靜態變量編譯時就已經分配了空間 |
.text | 一、只讀存儲區 -- 常量,const全局變量二、文本區 -- 程序代碼,機器代碼 |
0-4k保護區 |
#include<stdio.h> int a; //未初始化全局區 .bss int b=1; //已初始化全局區 .data static int c=2; //已初始化全局區 .data const int d=3; //只讀數據段,也叫文字常量區 ro.data, d的值不能被修改 int main(void) { int e=4; //棧區 static int f=5; //已初始化全局區 const int g=6; //棧區,不能經過變量名修改其值,但可經過其地址修改其值 int *p=malloc(sizeof(int)) //指針變量p在棧區,但其所指向的4字節空間在堆區 char *str="abcd"; //字符串「abcd」存在文字常量區,指針變量str在棧區,存的是「abcd」的起始地址 return 0; }
內存泄漏,是因爲疏忽或錯誤形成程序未能釋放掉再也不使用的內存。內存泄漏,並非指內存內存再物理地址上的消失,而是應用程序分配某段內存後,失去了對該段內存的控制,於是形成內存的浪費。ios
使用valgrind,mtrace來檢測內存泄漏c++
避免內存泄漏:git
1.事前預防型。如智能指針等。 2.過後查錯型。如泄漏檢測工具。github
使用智能指針,智能指針會自動刪除被分配的內存,他和普通指針相似,只是不須要手動釋放指針,智能指針本身管理內存釋放,不用擔憂內存泄漏問題面試
智能指針有:編程
其中auto_ptr c++11已經被棄用了後端
獨佔的智能指針,只能有一個對象擁有全部權,獨佔指針的是本身管理內存的,指針存在於棧空間,開闢的內存在堆空間,這裏的堆空間是和智能指針綁定的,智能指針隨着函數結束被銷燬以前,智能指針會先去把堆裏面的內存銷燬api
其中涉及數組
unique_ptr智能指針
的對象 如 auto myptr = make_unique<person>();
若是但願只有一個智能指針管理資源 就使用 unique_ptr
#include <iostream> #include <string> #include <memory> using namespace std; struct person { ~person() { cout<<"~person"<<endl; } string str; }; unique_ptr<person> test() { return unique_ptr<person> (new person); } int main() { //unique_ptr is ownership unique_ptr<person> p = test(); p->str = "hello world"; unique_ptr<person> p2 = move(p); //可使用move函數來轉移全部權,轉移全部權後,原來的指針就無權訪問 if(!p) { cout<<"p == null" <<endl; } if(p2) { cout<<"p2 have ownership"<<endl; cout<<p2->str<<endl; } p2.reset(new person);//能夠用reset函數來重置全部權,會把以前的對象全部權釋放掉,從新建立一個全部權對象 if(p2->str.empty()) { cout<<"str is null"<<endl; } return 0; }
共享的智能指針,shared_ptr
使用引用計數(use_count方法),每一個shared_ptr
的拷貝都指向同一塊內存,在最後一個shared_ptr被析構的時候,內存纔會被釋放
使用函數返回本身的shared_ptr
時,須要繼承enable_shared_from_this
類,使用shared_from_this函數進行返回
注意事項:
但願多個指針管理同一個資源就使用shared_ptr
#include <iostream> #include <string> #include <memory> using namespace std; struct person :enable_shared_from_this<person>{ string str; void show() { cout<<str<<endl; } ~person() { cout<<"~person"<<endl; } shared_ptr<person> getshared() { return shared_from_this(); } }; int main() { #if 0 shared_ptr<person> ptr(new person); cout<< ptr.use_count()<<endl; shared_ptr<person> ptr2 = ptr; cout<< ptr.use_count()<<endl; shared_ptr<person> a = make_shared<person>(); cout<< a.use_count()<<endl; a = ptr2; cout<< ptr.use_count()<<endl; shared_ptr<person> mm = a->getshared(); #endif shared_ptr<person> ptr; { shared_ptr<person> ptr2(new person); ptr2->str = "hello"; ptr = ptr2->getshared(); cout<< ptr.use_count()<<endl; } ptr->show(); return 0; }
弱引用的智能指針
是用來監視shared_ptr的,不會使用計數器加1,也不會使用計數器減1,主要是爲了監視shared_ptr的生命週期,更像是shared_ptr的一個助手。weak_ptr還能夠用來返回this指針和解決循環引用的問題。
shared_ptr會有循環引用的問題 ,解決方式爲 把類中的shared_ptr 換成 weak_ptr便可
struct ListNode { std::shared_ptr<ListNode> _next;//std::weak_ptr<ListNode> _next; 就能夠解決 std::shared_ptr<ListNode> _prev;//std::weak_ptr<ListNode> _pre; 就能夠解決 ~ListNode() { cout << "~ListNode()" << endl; } }; void test_shared_ptr_cycleRef() { std::shared_ptr<ListNode> cur(new ListNode); std::shared_ptr<ListNode> next(new ListNode); cur->_next = next; next->_prev = cur; } int main() { test_shared_ptr_cycleRef(); system("pause"); return 0; }
例如上述代碼案例
void shared_ptr_cycleRef(){ std::shared_ptr<LISTNODE> cur LISTNODE; std::shared_ptr<LISTNODE> next LISTNODE; cur->_next = next; next->_pre = cur; }
Cur 和 next 存在循環引用,他們的引用計數都變爲 2
出了做用域以後,cur 和 next 被銷燬,引用計數減 1
所以要釋放cur , 就須要釋放next 的 _pre,要釋放next , 就須要釋放cur 的 _next
valgrind的官方網址是:http://valgrind.org
valgrind被設計成非侵入式的,它直接工做於可執行文件上,所以在檢查前不須要從新編譯、鏈接和修改你的程序。要檢查一個程序很簡單
命令以下: valgrind --tool=tool_name program_name
valgrind --tool=memcheck ls -l
valgrind --tool=memcheck --leak-check=yes ls -l
valgrind有以下幾個工具:
memcheck
memcheck
探測程序中內存管理存在的問題。
它檢查全部對內存的讀/寫操做,並截取全部的malloc/new/free/delete
調用。所以memcheck工具可以探測到如下問題:
Memcheck 工具主要檢查下面的程序錯誤:
cachegrind
cachegrind 是一個cache剖析器。
它模擬執行CPU中的L1, D1和L2 cache,
所以它能很精確的指出代碼中的cache未命中。
它能夠打印出cache未命中的次數,內存引用和發生cache未命中的每一行 代碼,每個函數,每個模塊和整個程序的摘要。
若要求更細緻的信息,它能夠打印出每一行機器碼的未命中次數。
在x86和amd64上, cachegrind經過CPUID自動探測機器的cache配置,因此在多數狀況下它再也不須要更多的配置信息了。
helgrind
helgrind查找多線程程序中的競爭數據。
helgrind查找內存地址,那些被多於一條線程訪問的內存地址,可是沒有使用一致的鎖就會被查出。這表示這些地址在多線程間訪問的時候沒有進行同步,極可能會引發很難查找的時序問題。
在申請內存時
realloc是在C語言中出現的,c++已經摒棄realloc函數,realloc函數分配一塊新內存的時候,會把原內存中的內存copy到新內存中,經過memmove的方式
關鍵字和語法
編譯器能夠根據初始化來推導數據類型,不能用於函數傳參和以及數組類型推導
一種特殊類型的字面量,能夠被轉成任意的其餘類型
初始化類的列表
能夠實現移動語義和完美轉發,消除兩個對象交互時沒必要要的拷貝,節省存儲資源,提升效率
新增容器
智能指針,內存管理
新增 shared_ptr、weak_ptr用於內存管理
多線程
用於多線程互斥
其餘
能夠經過捕獲列表訪問上下文的數據
#ifndef
做用:相同的兩個文件不會被重複包含。
優勢:
缺點:
做用:物理上的同一個文件不會被重複包含。
優勢:
缺點:
「一種」
(a kind of )繼承 (如 男人 繼承 人類)
「一部分」
(a part of)組合(如 組合 眼 耳 口 鼻 -> 頭)
繼承與組合區別
繼承
優勢:
缺點:
組合
優勢:
缺點:
好處:簡化結構和程序通用性的問題,也是實現面向對象編程的一種途徑
做用:
inline函數是C++引入的機制,目的是解決使用宏定義的一些缺點。
用它替代宏定義,消除宏定義的缺點。
朋友們,你的支持和鼓勵,是我堅持分享,提升質量的動力
好了,本次就到這裏,下一次 GO的併發編程分享
技術是開放的,咱們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。
我是小魔童哪吒,歡迎點贊關注收藏,下次見~