程序員面試準備

內存分配形式

(1)BSS:用來存放程序中未初始化的全局數據和靜態數據的一塊內存區域,BSS屬於靜態內存分配,程序結束後靜態變量資源由系統自動釋放。
(2)數據段:用來存放程序中已經初始化的全局變量的一塊內存區域,數據段屬於靜態內存分配。包含static聲明的變量。
(3)代碼段:用來存放程序執行代碼(包括類成員函數和全局函數以及其他函數代碼)的一塊內存區域。這部分區域的大小在程序運行前就已經確定。
(4)堆:存放進程運行中被動態分配的內存段,大小不固定,如用malloc和new分配的內存就在堆上。堆一般由程序員自己釋放,若程序員不釋放,程序結束時由操作系統回收。它跟數據結構中的堆不是一回事,分配方式類似於鏈表。
(5)棧:存放臨時創建的局部變量,不包含static聲明的變量。棧由編譯器自動分配釋放。
棧是向下增長的,堆是向上增長的。
【注意】申請的效率不同:
棧:棧由系統自動分配,速度快,但是程序員無法控制。
堆:堆是有程序員自己分配,速度較慢,容易產生碎片,不過用起來方便。
棧上的數據的生存週期只是在函數的運行過程中,運行後就釋放掉,不可以再訪問。

內存泄漏

valgrind用於查內存泄漏
堆是動態分配內存的,並且可以分配很大的內存,使用不當就會產生內存泄漏,頻繁的使用malloc和new會產生內存碎片。所謂內存泄漏是由於疏忽或者錯誤造成程序未能釋放已經不再使用的內存的情況。一般常說的內存泄漏是指堆內存泄漏,因爲失去對該段內存的控制而造成的內存的浪費。一般用malloc或者是用new從堆中分配到一塊內存,用完以後一定要用free或者new來釋放掉,不然就會使得這塊內存不能再被使用,造成內存泄漏。
內存泄漏會出現導致系統出現CPU資源耗盡的嚴重後果。

TCP和UDP

TCP和UDP

TCP擁塞控制

擁塞控制

ARP

ARP

寫時複製

新建進程時,父進程和子進程共享內存,不進行復制,而且他們的訪問權限是隻讀,如果父進程或者是子進程有其一想要修改這些區域,則爲修改區域的那塊內存製作一個副本。

殭屍進程

殭屍進程是當一個子進程在其父進程還沒有調用wait()或waitpid()的情況就退出,以至於父進程沒有回收子進程,去釋放子進程佔用的資源,此時子進程將成爲一個殭屍進程。如果父進程先退出 ,子進程被init接管去回收其佔用的相關資源。
任何一個子進程(init除外)在exit()之後,並非馬上就消失,而是留下一個稱爲殭屍進程的數據結構等待父進程處理。如果子進程在exit()之後,父進程沒有來得及處理,那麼保留的那段信息就不會釋放,其進程號就會一直被佔用,但是系統所能使用的進程號是有限的,如果大量的產生僵死進程,將因爲沒有可用的進程號而導致系統不能產生新的進程。

孤兒進程

孤兒進程:一個父進程退出,而它的一個或多個子進程還在運行,那麼這些子進程將成爲孤兒進程。孤兒進程將被init進程所收養,並由init進程對它們完成狀態收集工作。每當出現一個孤兒進程的時候,內核就把孤兒進程的父進程設置爲init,而init進程會循環地wait()它的已經退出的子進程。孤兒進程沒有什麼危害。

進程與線程的區別

  1. 進程有自己獨立的內存,線程共享所屬進程的內存空間。
  2. 不同進程之間相互獨立;同一個進程的不同線程之間共享該進程的所有資源。
  3. 啓動一個進程要比啓動一個線程慢。
  4. 進程是一次程序執行,線程是程序中某一片段的執行。
  5. 進程是系統進行資源分配的基本單元,線程是CPU調度的基本單位。
  6. 一個線程只屬於一個進程,一個進程至少有一個線程。

fork和vfork

(1)fork是克隆一份父進程,包括數據段、堆和棧,代碼段共享,fork後父進程先執行還是子進程先執行取決於調度算法。fork子進程可以用於和父進程執行一樣的程序,也可以通過調用exec()執行新程序。
(2)vfork主要用於通過子進程執行新程序,所以並不會複製一份父進程,在調用exec()或者是exit()之前跟父進程共享內存,調用後用新程序資源。vfork後子進程先執行,然後父進程恢復執行。

進程間通信

進程間通信

線程同步有哪些機制

(1)臨界區:通過對多線程的串行化來訪問數據。
(2)互斥量:保證公共資源不會同時被多個線程訪問。
(3)信號量:允許多個線程在同一時刻訪問同一個資源。
(4)事件:用來通知線程事件已發生,通過設置標誌位。

虛擬內存

虛擬內存是相對於物理內存而言的,它使得應用程序以爲自己擁有連續可用的內存,其實它通常被分爲多個物理內存碎片,還有的在外部磁盤存儲器上,在需要時進行數據交換。
優點:
(1)擴大地址空間
(2)公平分配內存,每個進程都相當於有了同樣大小的虛存空間。
(3)可以實現進程間通過共享虛存通信。

cache替換算法

(1)隨機算法
(2)先進先出
(3)近期最少使用(LRU)Recently
(4)近期最少使用(LFU)Frequently
LRU關鍵是看頁面最後一次被使用到發生調度的時間長短;而LFU關鍵是看一定時間段內頁面被使用的頻率。

哈希表的衝突解決方式

哈希表:通過哈希函數把關鍵字和其位置一一對應
哈希函數的構造方法:
(1)直接定址法,根據k值確定位置。
(2)取餘法,用關鍵字k除以不大於哈希表長度的一個數(一般是哈希表長度,或者是不大於其的最大質數)
(3)數字分析法,如果實現已經知道了關鍵字的每一位分佈情況,並且關鍵字位數大於哈希表的地址位數(比如99就是兩位),可以選取關鍵字中比較均勻的幾位作爲哈希地址。
(4)平方取中法,取關鍵字進行平方運算後的中間幾位作爲哈希地址,取幾位由哈希表長度決定。
哈希解決衝突的辦法:
(1)線性探測:
當發生衝突的時候,從發生衝突的位置開始,向後一次探測空閒位置,如果到最後還沒有找到就從哈希表的第一個位置開始繼續查找。

容易發生聚集現象,比如哈希地址不同的關鍵字試圖佔用同一個新的地址。
只要哈希表未滿,一定能探測到空閒單元。

(2)平方探測:

避免了聚集
不一定能保證一定會探測到空間,因爲只探測了哈希表一半的空間。

(3)拉鍊法:
將衝突地址存儲在一個單鏈表中,哈希表的地址單元存儲的不再是數據,而是各個單鏈表的頭指針。

野指針

野指針是指向不可用內存指針,任何指針變量在創建時不會自動成爲NULL(空)指針,其默認值是隨機的,所以指針變量在創建的同時應該被初始化,或者將指針設置爲NULL,或者是指向合法內存,否則就會變成野指針。
同時指針通過free或者是delect把指針所指的內存給釋放掉了,但是並沒有把指針本身釋放掉,一般通過判斷是否是NULL來防錯,但是野指針既不是NULL又不指向合法內存。
第三種是指針操作超過了變量的作用範圍。

空指針

空指針是一個特殊的指針,也是唯一一個對任何指針類型都合法的指針,指針變量具有空指針值表示它當時處於閒置狀態,沒有指向有意義的內容。
通用指針可以指向任何類型的變量,通用指針的類型用(void*)表示,因此也稱爲void指針。

引用和指針的區別與聯繫

  1. 引用是定義一個變量來共享另一個變量的內存空間,來提高程序的併發效率;指針是指向另一個內存空間的變量,自己本身也有內存空間。
  2. 引用只能在定義時被初始化一次,之後不能再改變,引用其實是別名;指針也最好初始化,可以初始化爲NULL,但是它所指向的地址可以被改變。
  3. 引用時不需要解引用(*),指針需要。
  4. 對引用sizeof()得到的是所指向變量的大小;對指針sizeof()得到的是指針本身的大小。
  5. 指針和引用運用自增(++)不同,引用是值進行自增,而指針是地址進行自增。

malloc和new的區別

  1. malloc是庫函數,new是運算符
  2. malloc需要手動計算申請內存大小,new可以自動計算。
  3. malloc返回的指針是任意類型,new返回的類型是定義時指定的類型。
  4. new分3步,第一步調用operator new分配指定大小的空間,返回類型爲void*,其實質上是調用malloc實現的;第二步是強制類型轉換;第三步是在已分配好的空間上構造對象。
  5. malloc如果申請內存失敗,返回值是0;new實際上是在循環調用malloc,如果malloc返回爲0,就拋出異常並嘗試釋放空間來滿足需求,直到可以申請到空間。

局部變量、全局變量、靜態變量

局部變量:局部變量也只有局部作用域,它在程序運行期間不是一直存在,而是隻在函數執行期間存在,函數的一次調用執行結束後,變量被撤銷,其所佔用的內存也被收回。在棧上。
全局變量:全局變量具有全局作用域。全局變量只需在一個源文件中定義,就可以作用於所有的源文件。當然,其他不包含全局變量定義的源文件需要用extern關鍵字再次聲明這個全局變量。在數據段。
靜態局部變量:靜態局部變量具有局部作用域,它只被初始化一次,自從第一次被初始化直到程序運行結束都一直存在,靜態局部變量只對定義自己的函數體始終可見。
靜態全局變量:靜態全局變量也具有全局作用域,它與全局變量的區別在於如果程序包含多個文件的話,它作用於定義它的文件裏,不能作用到其它文件裏,即被static關鍵字修飾過的變量具有文件作用域。在數據段。

C++ 中class和struct的區別:

  1. 如果不做權限說明,class默認是private,struct默認是public。
  2. class可以用於定義模板參數,struct不可以。

public、protected和private繼承:

首先無論哪一種繼承,子類只能訪問基類的public和protected成員,不能訪問private成員。

  1. public繼承不改變基類的成員屬性;
  2. protected繼承將基類的public轉換爲protected;
  3. private繼承將基類的public和protected轉化爲private。

gdb的基本命令

c 繼續運行
n 單步運行(不進入函數)
s 如果有函數則進入函數執行
p 變量名 打印變量的值
b 函數名 設置斷點
d 斷點號 刪除斷點
q 退出
i b 輸出所有斷點
bt 查看調用棧

算法

第一個只出現一次的字符
快排
快排優化
刪除排序數組中的重複項
二叉樹的中序遍歷
二叉樹的層次遍歷
二叉樹的前序遍歷
二叉樹的後序遍歷
反轉鏈表
環形鏈表
環形鏈表 II
鏈表中倒數第k個結點
刪除鏈表的倒數第N個節點
前K個高頻單詞
最大堆
兩數之和
迴文鏈表
二叉樹的所有路徑
相交鏈表
數組中的第K個最大元素
最大子序和
無重複字符的最長子串
合併兩個有序鏈表
數據流中的中位數
對稱二叉樹
strcpy與strncpy函數的區別及其C語言實現過程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章