嵌入式面試高頻考點(diǎn)(建議收藏)

本篇參考網(wǎng)上及自身的面試經(jīng)驗(yàn),總結(jié)一些高頻考察的Linux C/C++知識(shí)點(diǎn)耗绿,方便后續(xù)查閱總結(jié)吓妆。

一、C/C++編程基礎(chǔ)

  1. C++多態(tài)的實(shí)現(xiàn)
    virtual關(guān)鍵字修飾基類(lèi)的成員函數(shù)宣渗,派生類(lèi)中重寫(xiě)此函數(shù)抖所,實(shí)現(xiàn)多態(tài)

  2. C++四種強(qiáng)制類(lèi)型轉(zhuǎn)換

  • static_cast
    static_cast<type>(expression)
    該運(yùn)算符把 expression 轉(zhuǎn)換為 type 類(lèi)型,主要用于基本數(shù)據(jù)類(lèi)型之間的轉(zhuǎn)換痕囱,如把 uint 轉(zhuǎn)換為 int田轧,把 int 轉(zhuǎn)換為 double 等。
    另外鞍恢,static_cast 還可用于類(lèi)層次結(jié)構(gòu)中傻粘,基類(lèi)和派生類(lèi)之間指針或引用的轉(zhuǎn)換,但也要注意:
    static_cast 進(jìn)行上行轉(zhuǎn)換是安全的帮掉,即把派生類(lèi)的指針轉(zhuǎn)換為基類(lèi)的弦悉;
    static_cast 進(jìn)行下行轉(zhuǎn)換是不安全的,即把基類(lèi)的指針轉(zhuǎn)換為派生類(lèi)的蟆炊。
    注:static_cast 沒(méi)有運(yùn)行時(shí)類(lèi)型檢查來(lái)保證轉(zhuǎn)換的安全性稽莉,需要程序員來(lái)判斷轉(zhuǎn)換是否安全。
uint x = 1;
int y = static_cast<int>(x); // 轉(zhuǎn)換正確

int x = 1;
double y = static_cast<double>(x); // 轉(zhuǎn)換正確

// 上行轉(zhuǎn)換涩搓,派生類(lèi)→基類(lèi)
Derive* d = new Derive();
Base* b = static_cast<Base*>(d);

// 下行轉(zhuǎn)換污秆,基類(lèi)→派生類(lèi)
Base* b = new Base();
Derive* d = static_cast<Derive*>(b);
  • const_cast
    const_cast<type>(expression)
    主要是用來(lái)去除復(fù)合類(lèi)型中const和volatile屬性(沒(méi)有真正去除)。expression 和 type 的類(lèi)型需要保持一致昧甘。

  • dynamic_cast
    dynamic_cast<type>(expression)
    主要用于類(lèi)層次間的上行轉(zhuǎn)換或下行轉(zhuǎn)換良拼。在進(jìn)行上行轉(zhuǎn)換時(shí),dynamic_cast 和 static_cast 的效果是一樣的充边,但在下行轉(zhuǎn)換時(shí)庸推,dynamic_cast 具有類(lèi)型檢查的功能,比 static_cast 更安全。

  • reinterpret_cast
    reinterpret_cast<type>(expression)
    該運(yùn)算符可以把一個(gè)指針轉(zhuǎn)換成一個(gè)整數(shù)贬媒,也可以把一個(gè)整數(shù)轉(zhuǎn)換成一個(gè)指針刮吧。

  1. static的作用
  • 限制變量或函數(shù)作用域
    被static關(guān)鍵字修飾的全局函數(shù)或者變量具有文件作用域,即只在當(dāng)前文件中可見(jiàn)掖蛤。

  • 保持變量?jī)?nèi)容的持久
    被static修飾的變量會(huì)被存儲(chǔ)在靜態(tài)存儲(chǔ)區(qū)杀捻,生命周期也為從定義直至程序結(jié)束。對(duì)于局部變量蚓庭,即使在函數(shù)退出后該靜態(tài)變量依然存在致讥,然而卻也無(wú)法訪問(wèn)。此外器赞,static修飾的變量一生只會(huì)被初始化一次垢袱。

  • 默認(rèn)初始化為0
    因?yàn)楸籹tatic修飾的變量會(huì)被存儲(chǔ)在靜態(tài)存儲(chǔ)區(qū),所以才有了這個(gè)一條港柜。因?yàn)殪o態(tài)存儲(chǔ)區(qū)的變量會(huì)被默認(rèn)初始化為0请契。

除此之外,在C++中夏醉,static也可以類(lèi)成員變量和類(lèi)成員函數(shù)爽锥。

  • 類(lèi)的靜態(tài)成員函數(shù)是屬于整個(gè)類(lèi)而非類(lèi)的對(duì)象,所以它沒(méi)有this指針畔柔,這就導(dǎo)致 了它僅能訪問(wèn)類(lèi)的靜態(tài)數(shù)據(jù)和靜態(tài)成員函數(shù)氯夷。

  • 靜態(tài)成員函數(shù)不含有this指針,所以可以作為回調(diào)函數(shù)靶擦。但同時(shí)為了可以訪問(wèn)類(lèi)的成員變量可以將對(duì)象的this指針當(dāng)做實(shí)參傳入回調(diào)函數(shù)中腮考。

  • 靜態(tài)成員函數(shù)在類(lèi)定義體外定義時(shí)不能加static關(guān)鍵字修飾,因?yàn)槌蓡T函數(shù)本是類(lèi)作用域玄捕,而在類(lèi)外用static修飾會(huì)將其作用于擴(kuò)大為文件作用域踩蔚,所以是不合理的。

  • 靜態(tài)成員變量并不像一般的成員變量在構(gòu)造函數(shù)中初始化枚粘,而是在類(lèi)的實(shí)現(xiàn)文件中初始化馅闽,即必須在.cpp文件中初始化,否則在程序鏈接時(shí)會(huì)出錯(cuò)赌结,重定義捞蛋,且初始化時(shí)無(wú)需再使用static關(guān)鍵字修飾孝冒。

  • static修飾的const成員變量可以再類(lèi)中被定義時(shí)初始化柬姚。

  • 利用static只會(huì)被初始化一次的特性,可以實(shí)現(xiàn)單例對(duì)象庄涡。

  1. extern 有什么作用
    extern用在變量或者函數(shù)的聲明前量承,用來(lái)說(shuō)明“此變量/函數(shù)是在別處定義的,要在此處引用”。extern聲明既不是定義撕捍,也不分配存儲(chǔ)空間拿穴。

  2. 說(shuō)一說(shuō)const關(guān)鍵字
    const關(guān)鍵字告訴了編譯器,它修飾的目標(biāo)值不能被改變忧风,如果代碼中發(fā)現(xiàn)有類(lèi)似改變?cè)撟兞康牟僮髂敲淳幾g器就會(huì)捕捉這個(gè)錯(cuò)誤。修飾函數(shù)時(shí)狮腿,
    好的編程習(xí)慣告誡程序員腿宰,當(dāng)不需要改變的變量,最好使用const修飾缘厢,例如非頭文件定義的常量吃度,最好用const而非define。

  3. sizeof 和 strlen 的區(qū)別

  • sizeof會(huì)將空字符\0計(jì)算在內(nèi)贴硫,而strlen不會(huì)將空字符\0計(jì)算在內(nèi)椿每;
  • sizeof會(huì)計(jì)算到字符串最后一個(gè)空字符\0并結(jié)束,而strlen如果遇到第一個(gè)空字符\0的話就會(huì)停止并計(jì)算遇到的第一個(gè)空字符\0前面的長(zhǎng)度英遭。
  1. #define和const的區(qū)別
  • #define 只是在預(yù)處理階段簡(jiǎn)單的做字符替換间护,其可以實(shí)現(xiàn)宏函數(shù)和變量等;const是在編譯挖诸、運(yùn)行階段起作用兑牡,修飾變量。

  • const 定義的常數(shù)是變量也帶類(lèi)型税灌,#define 定義的只是個(gè)常數(shù) 不帶類(lèi)型均函。

  • #define只是簡(jiǎn)單的字符串替換,沒(méi)有類(lèi)型檢查菱涤。而const有對(duì)應(yīng)的數(shù)據(jù)類(lèi)型苞也,是要進(jìn)行判斷的,可以避免一些低級(jí)的錯(cuò)誤粘秆。

  • #define屬于預(yù)處理如迟,會(huì)占用代碼空間;const+類(lèi)型定義屬于變量定義攻走,占用數(shù)據(jù)段空間殷勘。

  1. 一個(gè)指針可以是 volatile 嗎
    可以。volatile關(guān)鍵詞修飾的變量意思為值可能會(huì)改變昔搂,指針是可以改變的玲销,與const關(guān)鍵詞相反。

  2. 定義和聲明的區(qū)別
    聲明是將一個(gè)名稱引入程序摘符,定義提供了一個(gè)實(shí)體在程序中的唯一描述贤斜。

  3. 什么是野指針
    訪問(wèn)一個(gè)已銷(xiāo)毀或者訪問(wèn)受限的內(nèi)存區(qū)域的指針策吠。野指針的使用,可能會(huì)引起程序崩潰瘩绒,且無(wú)法用NULL檢測(cè)野指針猴抹。

  4. 指針和引用的區(qū)別
    指針是一個(gè)變量,存儲(chǔ)的是一個(gè)地址锁荔,指向內(nèi)存的一個(gè)存儲(chǔ)單元蟀给,指針變量占用內(nèi)存;
    引用是原變量的一個(gè)別名阳堕,跟原來(lái)的變量實(shí)質(zhì)上是同一個(gè)東西坤溃,引用變量不占用內(nèi)存。

  5. 簡(jiǎn)述指針常量與常量指針區(qū)別
    指針常量:本質(zhì)是一個(gè)常量嘱丢,而用指針修飾它薪介。指針常量的值是指針,這個(gè)值因?yàn)槭浅A吭阶ぃ圆荒鼙毁x值汁政。
    常量指針:又叫常指針,可以理解為常量的指針缀旁,也即這個(gè)是指針记劈,但指向的是個(gè)常量,這個(gè)常量是指針的值(地址)并巍,而不是地址指向的值目木。

  6. 引用作為函數(shù)參數(shù)以及返回值的好處
    在內(nèi)存中不產(chǎn)生被返回值的副本。(注意:正是因?yàn)檫@點(diǎn)原因懊渡,所以返回一個(gè)局部變量的引用是不可取的刽射。因?yàn)殡S著該局部變量生存期的結(jié)束,相應(yīng)的引用也會(huì)失效剃执,產(chǎn)生runtime error!)

  7. 談?wù)凜++內(nèi)存管理

    內(nèi)存管理32位.png

  • stack棧區(qū):專門(mén)用來(lái)實(shí)現(xiàn)函數(shù)調(diào)用-棧結(jié)構(gòu)的內(nèi)存塊誓禁。相對(duì)空間下(可以設(shè)置大小,Linux 一般默認(rèn)是8M肾档,可通過(guò) ulimit –s 查看)摹恰,系統(tǒng)自動(dòng)管理,從高地址往低地址怒见,向下生長(zhǎng)俗慈。

  • 內(nèi)存映射區(qū):包括文件映射和匿名內(nèi)存映射, 應(yīng)用程序的所依賴的動(dòng)態(tài)庫(kù)遣耍,會(huì)在程序執(zhí)行時(shí)候闺阱,加載到內(nèi)存這個(gè)區(qū)域,一般包括數(shù)據(jù)(data)和代碼(text);通過(guò)mmap系統(tǒng)調(diào)用配阵,可以把特定的文件映射到內(nèi)存中馏颂,然后在相應(yīng)的內(nèi)存區(qū)域中操作字節(jié)來(lái)訪問(wèn)文件內(nèi)容,實(shí)現(xiàn)更高效的IO操作棋傍;匿名映射救拉,在glibc中malloc分配大內(nèi)存的時(shí)候會(huì)用到匿名映射。這里所謂的“大”表示是超過(guò)了MMAP_THRESHOLD 設(shè)置的字節(jié)數(shù)瘫拣,它的缺省值是 128 kB亿絮,可以通過(guò) mallopt() 去調(diào)整這個(gè)設(shè)置值。還可以用于進(jìn)程間通信IPC(共享內(nèi)存)麸拄。

  • heap堆區(qū):主要用于用戶動(dòng)態(tài)內(nèi)存分配派昧,空間大,使用靈活拢切,但需要用戶自己管理蒂萎,通過(guò)brk系統(tǒng)調(diào)用控制堆的生長(zhǎng),向高地址生長(zhǎng)淮椰。

  • BBS段和DATA段:用于存放程序全局?jǐn)?shù)據(jù)和靜態(tài)數(shù)據(jù)五慈,一般未初始化的放在BSS段(統(tǒng)一初始化為0,不占程序文件的空間)主穗,初始化的放在data段泻拦,只讀數(shù)據(jù)放在rodata段(常量存儲(chǔ)區(qū))。

  • text段:主要存放程序二進(jìn)制代碼忽媒。

  1. 談?wù)刵ew争拐、delete、malloc晦雨、free

共同點(diǎn):

  • 都是從堆上申請(qǐng)空間架曹,并且需要用戶手動(dòng)釋放。

不同點(diǎn):

  • malloc和free是函數(shù)闹瞧,new和delete是操作符

  • malloc申請(qǐng)的空間不會(huì)初始化音瓷,new可以初始化

  • malloc申請(qǐng)空間時(shí),需要手動(dòng)計(jì)算空間大小并傳遞夹抗,new只需在其后跟上空間的類(lèi)型即可绳慎。

  • malloc的返回值為void*, 在使用時(shí)必須強(qiáng)轉(zhuǎn),new不需要漠烧,因?yàn)閚ew后跟的是空間的類(lèi)型杏愤。

  • malloc申請(qǐng)空間失敗時(shí),返回的是NULL已脓,因此使用時(shí)必須判空珊楼,new不需要,但是new需要捕獲異常度液。

  • 申請(qǐng)自定義類(lèi)型對(duì)象時(shí)厕宗,malloc/free只會(huì)開(kāi)辟空間画舌,不會(huì)調(diào)用構(gòu)造函數(shù)與析構(gòu)函數(shù),而new在申請(qǐng)空間后會(huì)調(diào)用構(gòu)造函數(shù)完成對(duì)象的初始化已慢,delete在釋放空間前會(huì)調(diào)用析構(gòu)函數(shù)完成空間中資源的清理曲聂。

  1. delete和delete[]的區(qū)別
    delete只會(huì)調(diào)用一次析構(gòu)函數(shù),而delete []會(huì)調(diào)用每一個(gè)成員的析構(gòu)函數(shù)佑惠。

  2. 簡(jiǎn)述 strcpy朋腋、sprintf 與 memcpy 的區(qū)別
    操作對(duì)象不同,strcpy 的兩個(gè)操作對(duì)象均為字符串; sprintf 的操作源對(duì)象可以是多種數(shù)據(jù)類(lèi)型膜楷,目的操作對(duì)象是字符串; memcpy 的兩個(gè)對(duì)象就是兩個(gè)任意可操作的內(nèi)存地址旭咽,并不限于何種數(shù)據(jù)類(lèi)型。

  3. C++的空類(lèi)有哪些成員函數(shù)
    一個(gè)默認(rèn)構(gòu)造函數(shù)赌厅、一個(gè)拷貝默認(rèn)構(gòu)造函數(shù)穷绵、一個(gè)默認(rèn)拷貝賦值操作符和一個(gè)默認(rèn)析構(gòu)函數(shù)。這些函數(shù)只有在第一次被調(diào)用時(shí)特愿,才會(huì)被編譯器創(chuàng)建请垛。所有這些函數(shù)都是inline和public的。

  4. 構(gòu)造函數(shù)為什么不能是虛函數(shù)

  • 構(gòu)造一個(gè)對(duì)象的時(shí)候洽议,必須知道對(duì)象的實(shí)際類(lèi)型宗收,而虛函數(shù)行為是在運(yùn)行期間確定實(shí)際類(lèi)型的。而在構(gòu)造一個(gè)對(duì)象時(shí)亚兄,由于對(duì)象還未構(gòu)造成功混稽。編譯器無(wú)法知道對(duì)象 的實(shí)際類(lèi)型,是該類(lèi)本身审胚,還是該類(lèi)的一個(gè)派生類(lèi)匈勋,或是更深層次的派生類(lèi)。無(wú)法確定膳叨。洽洁。。

  • 虛函數(shù)的執(zhí)行依賴于虛函數(shù)表菲嘴。而虛函數(shù)表在構(gòu)造函數(shù)中進(jìn)行初始化工作饿自,即初始化vptr,讓他指向正確的虛函數(shù)表龄坪。而在構(gòu)造對(duì)象期間昭雌,虛函數(shù)表還沒(méi)有被初始化,將無(wú)法進(jìn)行健田。

  1. 深拷貝和淺拷貝的區(qū)別
  • 淺拷貝: 與拷貝對(duì)象共享同一片內(nèi)存烛卧。只復(fù)制對(duì)象的基本類(lèi)型,對(duì)象類(lèi)型,仍屬于原來(lái)的引用。

  • 深拷貝: 申請(qǐng)新的內(nèi)存妓局,并將目標(biāo)對(duì)象復(fù)制到新的內(nèi)存总放。

  1. 知道STL嗎呈宇,挑兩個(gè)你最常用的容器說(shuō)一說(shuō)

容器分為兩大類(lèi): 順序容器和關(guān)聯(lián)容器

  1. STL中的vector的實(shí)現(xiàn),是怎么擴(kuò)容的
    vector 為空的時(shí)候沒(méi)有預(yù)分配空間握截,每次添加一個(gè)元素時(shí)飞崖,會(huì)判斷當(dāng)前是否還有剩余可用空間,如果沒(méi)有則進(jìn)行試探性擴(kuò)容谨胞,并且把內(nèi)存拷貝到新申請(qǐng)的內(nèi)存空間上固歪,并且釋放原先的內(nèi)存。

  2. C++中vector和list的區(qū)別
    vector是動(dòng)態(tài)數(shù)組胯努,內(nèi)部存儲(chǔ)是一片連續(xù)性的空間牢裳,支持通過(guò)下標(biāo)隨機(jī)訪問(wèn)。

    list是雙向鏈表叶沛,內(nèi)部存儲(chǔ)可能是不連續(xù)的空間蒲讯,通過(guò)指針鏈接這些不連續(xù)的空間,不支持隨機(jī)訪問(wèn)灰署。

  3. 怎么確定一個(gè)程序是C編譯的還是C++編譯的
    如果編譯器在編譯cpp文件那么__cplusplus就會(huì)被定義 如果是一個(gè)c文件在被編譯那么__STDC__就會(huì)被定義判帮。

  4. 說(shuō)一下什么是內(nèi)存泄漏,如何避免
    是指程序在申請(qǐng)內(nèi)存后氓侧,無(wú)法釋放已申請(qǐng)的內(nèi)存空間脊另,稱之為內(nèi)存泄露。無(wú)法釋放的內(nèi)存會(huì)一直被無(wú)效占用约巷,且無(wú)法被再次使用偎痛,累計(jì)下來(lái)會(huì)導(dǎo)致進(jìn)程占用內(nèi)存越來(lái)越大,直至無(wú)內(nèi)存資源可用独郎,導(dǎo)致進(jìn)程崩潰踩麦。

  5. C++中內(nèi)存泄漏的幾種情況

  • 在類(lèi)的構(gòu)造函數(shù)和析構(gòu)函數(shù)中沒(méi)有匹配的調(diào)用new和delete函數(shù)

  • 沒(méi)有正確地清除嵌套的對(duì)象指針

  • 在釋放對(duì)象數(shù)組時(shí)在delete中沒(méi)有使用方括號(hào)

  • 指向?qū)ο蟮闹羔様?shù)組不等同于對(duì)象數(shù)組

  • 缺少拷貝構(gòu)造函數(shù)

  • 缺少重載賦值運(yùn)算符

  • 沒(méi)有將基類(lèi)的析構(gòu)函數(shù)定義為虛函數(shù)

  1. 一個(gè)文件從源碼到可執(zhí)行文件所經(jīng)歷的過(guò)程
    ① 預(yù)處理,產(chǎn)生.ii文件
    ② 編譯氓癌,產(chǎn)生匯編文件 (.s文件)
    ③ 匯編谓谦,產(chǎn)生目標(biāo)文件 (.o或.obj文件)
    ④ 鏈接,產(chǎn)生可執(zhí)行文件

  2. 聊聊C++11新特性

  3. C++構(gòu)造函數(shù)和析構(gòu)函數(shù)的調(diào)用順序
    構(gòu)造函數(shù)順序: 基類(lèi)構(gòu)造函數(shù)贪婉、對(duì)象成員構(gòu)造函數(shù)反粥、派生類(lèi)本身的構(gòu)造函數(shù)。
    析構(gòu)函數(shù)順序: 派生類(lèi)本身的析構(gòu)函數(shù)、對(duì)象成員析構(gòu)函數(shù)才顿、基類(lèi)析構(gòu)函數(shù)(與構(gòu)造順序正好相反)莫湘。

  4. 用 C++設(shè)計(jì)一個(gè)不能被繼承的類(lèi)
    將自身構(gòu)造函數(shù)和析構(gòu)函數(shù)聲明為private。

  5. 什么是純虛函數(shù)
    基類(lèi)中聲明的虛函數(shù)郑气,僅有聲明無(wú)實(shí)現(xiàn)幅垮。要求派生的子類(lèi)必須定義自身的實(shí)現(xiàn)方法,達(dá)到多態(tài)效果尾组。

  6. 構(gòu)造函數(shù)為什么一般不定義為虛函數(shù)忙芒?而析構(gòu)函數(shù)一般寫(xiě)成虛函數(shù)的原因

  • 構(gòu)造函數(shù)不能聲明為虛函數(shù)
    因?yàn)閯?chuàng)建一個(gè)對(duì)象時(shí)需要確定對(duì)象的類(lèi)型,而虛函數(shù)是在運(yùn)行時(shí)確定其類(lèi)型的讳侨。而在構(gòu)造一個(gè)對(duì)象時(shí)呵萨,由于對(duì)象還未創(chuàng)建成功,編譯器無(wú)法知道對(duì)象的實(shí)際類(lèi)型爷耀,是類(lèi)本身還是類(lèi)的派生類(lèi)等等

    虛函數(shù)的調(diào)用需要虛函數(shù)表指針甘桑,而該指針存放在對(duì)象的內(nèi)存空間中拍皮;若構(gòu)造函數(shù)聲明為虛函數(shù)歹叮,那么由于對(duì)象還未創(chuàng)建,還沒(méi)有內(nèi)存空間铆帽,更沒(méi)有虛函數(shù)表地址用來(lái)調(diào)用虛函數(shù)即構(gòu)造函數(shù)了

  • 析構(gòu)函數(shù)最好聲明為虛函數(shù)

    首先析構(gòu)函數(shù)可以為虛函數(shù)咆耿,當(dāng)析構(gòu)一個(gè)指向派生類(lèi)的基類(lèi)指針時(shí),最好將基類(lèi)的析構(gòu)函數(shù)聲明為虛函數(shù)爹橱,否則可以存在內(nèi)存泄露的問(wèn)題萨螺。

    如果析構(gòu)函數(shù)不被聲明成虛函數(shù),則編譯器實(shí)施靜態(tài)綁定愧驱,在刪除指向派生類(lèi)的基類(lèi)指針時(shí)慰技,只會(huì)調(diào)用基類(lèi)的析構(gòu)函數(shù)而不調(diào)用派生類(lèi)析構(gòu)函數(shù),這樣就會(huì)造成派生類(lèi)對(duì)象析構(gòu)不完全组砚。

  1. 析構(gòu)函數(shù)的作用
    對(duì)象消亡時(shí)吻商,自動(dòng)被調(diào)用,用來(lái)釋放對(duì)象占用的空間糟红。

  2. 棧和堆的區(qū)別艾帐,什么時(shí)候必須使用堆

  • 棧:為函數(shù)分配的一塊內(nèi)存,函數(shù)內(nèi)部聲明的所有局部變量都將占用棧內(nèi)存盆偿。函數(shù)執(zhí)行完畢后柒爸,占用的棧會(huì)被銷(xiāo)毀回收,內(nèi)部定義的變量均會(huì)銷(xiāo)毀事扭。效率很高捎稚,但是分配的內(nèi)存容量有限。

  • 堆:程序中未使用的內(nèi)存,在程序運(yùn)行時(shí)可用于動(dòng)態(tài)分配內(nèi)存今野。由程序員自己維護(hù)申請(qǐng)和回收晰奖,若使用完畢未回收會(huì)導(dǎo)致內(nèi)存泄漏。

  1. 棧溢出(stack overflow)的原因以及解決方法
  • 棧溢出原因
    ① 局部數(shù)組過(guò)大腥泥。當(dāng)函數(shù)內(nèi)部的數(shù)組過(guò)大時(shí)匾南,有可能導(dǎo)致堆棧溢出。

    ② 遞歸調(diào)用層次太多蛔外。遞歸函數(shù)在運(yùn)行時(shí)會(huì)執(zhí)行壓棧操作蛆楞,當(dāng)壓棧次數(shù)太多時(shí),也會(huì)導(dǎo)致堆棧溢出夹厌。

    ③ 指針或數(shù)組越界豹爹。這種情況最常見(jiàn),例如進(jìn)行字符串拷貝矛纹,或處理用戶輸入等等臂聋。

  • 解決方法
    增大棧空間; 變量過(guò)大時(shí)或南,改用動(dòng)態(tài)分配孩等,使用堆(heap)而不是棧(stack)。

  1. 編碼實(shí)現(xiàn)某一變量某位清 0 或置 1
// 將第index為置1. index: 0~7
unsigned char set_bit(unsigned char value, int index)
{
    return value | (1 << index);
}

//將第index位清0, index: 0~7
unsigned char clear_bit(unsigned char value, int index)
{
    return value & (~(1 << index));
}
  1. 頭文件<>和""的區(qū)別
  • <>: 表示引用標(biāo)準(zhǔn)庫(kù)頭文件采够,編譯器會(huì)從系統(tǒng)默認(rèn)庫(kù)環(huán)境路徑查找肄方。

  • "": 一般表示用戶自己定義使用的頭文件,編譯器默認(rèn)會(huì)優(yōu)先從當(dāng)前路徑中尋找蹬癌;若未找到权她,再?gòu)南到y(tǒng)默認(rèn)庫(kù)環(huán)境路徑中去查找。

注:linux下C和C++默認(rèn)庫(kù)環(huán)境路徑:/usr/include

  1. 靜態(tài)綁定和動(dòng)態(tài)綁定的介紹

把一個(gè)方法與其所在的類(lèi)/對(duì)象關(guān)聯(lián)起來(lái)叫做方法的綁定逝薪。

靜態(tài)類(lèi)型:對(duì)象在聲明時(shí)采用的類(lèi)型隅要,在編譯期既已確定。

動(dòng)態(tài)類(lèi)型:通常是指一個(gè)指針或引用目前所指對(duì)象的類(lèi)型董济,是在運(yùn)行期決定的步清。

靜態(tài)綁定:綁定的是靜態(tài)類(lèi)型,所對(duì)應(yīng)的函數(shù)或?qū)傩砸蕾囉趯?duì)象的靜態(tài)類(lèi)型感局,發(fā)生在編譯期尼啡。

動(dòng)態(tài)綁定:綁定的是動(dòng)態(tài)類(lèi)型,所對(duì)應(yīng)的函數(shù)或?qū)傩砸蕾囉趯?duì)象的動(dòng)態(tài)類(lèi)型询微,發(fā)生在運(yùn)行期崖瞭。

非虛函數(shù)一般都是靜態(tài)綁定,而虛函數(shù)都是動(dòng)態(tài)綁定(如此才可實(shí)現(xiàn)多態(tài)性)

  1. 引用是否能實(shí)現(xiàn)動(dòng)態(tài)綁定撑毛,為什么引用可以實(shí)現(xiàn)
    可以书聚。引用在創(chuàng)建的時(shí)候必須初始化唧领,在訪問(wèn)虛函數(shù)時(shí),編譯器會(huì)根據(jù)其所綁定的對(duì)象類(lèi)型決定要調(diào)用哪個(gè)函數(shù)雌续。注意只能調(diào)用虛函數(shù)斩个。

  2. 什么情況下會(huì)調(diào)用拷貝構(gòu)造函數(shù)(三種情況)
    拷貝構(gòu)造函數(shù)從來(lái)不顯示調(diào)用,而是由編譯器隱式地調(diào)用驯杜。
    ① 用類(lèi)的一個(gè)對(duì)象去初始化另一個(gè)對(duì)象時(shí)受啥;
    ② 當(dāng)函數(shù)的形參是類(lèi)的對(duì)象時(shí)(也就是值傳遞時(shí)),如果是引用傳遞則不會(huì)調(diào)用鸽心;
    ③ 當(dāng)函數(shù)的返回值是類(lèi)的對(duì)象或引用時(shí)滚局。

  3. extern "C"作用
    extern "C" 的 主要 作用 就 是 為了能夠正確實(shí)現(xiàn)C++代碼調(diào)用其他C語(yǔ)言代碼。加上extern "C"后顽频,編譯器會(huì)按照C語(yǔ)言語(yǔ)法進(jìn)行編譯藤肢。

  4. typedef和define的區(qū)別

typedef和define都是替一個(gè)對(duì)象取一個(gè)別名,以此增強(qiáng)程序的可讀性糯景。
①作用階段不同
typedef: 編譯階段有效, 有類(lèi)型檢查的功能嘁圈。
define: 預(yù)處理階段有效, 編譯前, 只進(jìn)行簡(jiǎn)單而機(jī)械的字符串替換, 不進(jìn)行任何檢查。
② 功能不同
typedef: 用來(lái)定義類(lèi)型(內(nèi)部或自定義類(lèi)型)的別名, 起到使類(lèi)型易于記憶的功能蟀淮。
define: 不止可以為類(lèi)型取別名, 還可以定義常量, 變量, 編譯開(kāi)關(guān)等最住。
作用域不同
typedef: 與變量生命期類(lèi)似。放在函數(shù)外灭贷,作用域從定義開(kāi)始到文件尾温学;若放在函數(shù)內(nèi)略贮,定義域從定義處到該函數(shù)結(jié)尾甚疟。
define 沒(méi)有作用域的限制,從定義開(kāi)始到文件結(jié)尾逃延。

//源自https://www.cnblogs.com/retry/p/14045305.html
//a.c
 typedef …//此處開(kāi)始到文件結(jié)尾
 #define …//此處開(kāi)始到文件結(jié)尾
 int negate(int num)
 {
 …
     typedef …//此處開(kāi)始到該函數(shù)結(jié)束览妖。注意,該函數(shù)內(nèi)揽祥,此定義前讽膏,也不能用
     #define …//此處開(kāi)始到文件結(jié)尾
 …
 }
 typedef …//此處開(kāi)始到文件結(jié)尾
 #define …//此處開(kāi)始到文件結(jié)尾
 void show()
 {
     typedef …//此處開(kāi)始到該函數(shù)結(jié)束。
     #define …//此處開(kāi)始到文件結(jié)尾
 }

④ 對(duì)指針的操作:
二者修飾指針類(lèi)型時(shí), 作用不同拄丰。

Typedef int * pint府树;  
#define PINT int *  
const pint p;//p不可更改料按,p指向的內(nèi)容可以更改奄侠,相當(dāng)于 int * const p;  
const PINT p;//p可以更改载矿,p指向的內(nèi)容不能更改垄潮,相當(dāng)于 const int *p;或 int const *p;  
pint s1, s2; //s1和s2都是int型指針  
PINT s3, s4; //相當(dāng)于int * s3弯洗,s4旅急;只有一個(gè)是指針。 
  1. 友元函數(shù)和友元類(lèi)
  • 友元函數(shù)
    類(lèi)的友元函數(shù)是定義在類(lèi)外部牡整,但有權(quán)訪問(wèn)類(lèi)的所有私有(private)成員和保護(hù)(protected)成員藐吮。盡管友元函數(shù)的原型有在類(lèi)的定義中出現(xiàn)過(guò)逃贝,但是友元函數(shù)并不是成員函數(shù)。

  • 友元類(lèi)
    在類(lèi)A中秋泳,用friend修飾另一個(gè)已經(jīng)定義的類(lèi)B,類(lèi)B就屬于類(lèi)A的友元類(lèi)迫皱,類(lèi)B中的所有成員函數(shù)都是類(lèi)A的友元函數(shù)歉闰,類(lèi)B可以訪問(wèn)類(lèi)A的所有成員和敬,包括 publicprotected戏阅、private 屬性的昼弟。

  1. 提高c++性能奕筐,你用過(guò)哪些方式去提升
  • 空間足夠時(shí),可以將經(jīng)常需要讀取的資源芭逝,緩存在內(nèi)存中渊胸。
  • 盡量減少大內(nèi)存對(duì)象的構(gòu)造與析構(gòu),考慮緩存暫時(shí)不用的對(duì)象胖翰,等待后續(xù)繼續(xù)使用切厘。
  • 盡量使用C++11的右值語(yǔ)義,減少臨時(shí)對(duì)象的構(gòu)造某弦。
  • 簡(jiǎn)單的功能函數(shù)可以使用內(nèi)聯(lián)。少用繼承靶壮,多用組合腾降,盡量減少繼承層級(jí)。
  • 在循環(huán)遍歷時(shí)螃壤,優(yōu)化判斷條件奸晴,減少循環(huán)次數(shù)冤馏。
  • 優(yōu)化線程或進(jìn)程的同步方式,能用原子操作的就不用鎖寄啼。能應(yīng)用層同步的就不用內(nèi)核對(duì)象同步。
  • 優(yōu)化堆內(nèi)存的使用涕刚,如果有內(nèi)存頻繁的申請(qǐng)與釋放乙帮,可以考慮內(nèi)存池。
  • 優(yōu)化線程的使用驾茴,節(jié)省系統(tǒng)資源與切換造成的性能損耗,線程使用頻繁的可以考慮線程池塞绿。
  • 盡量使用事件通知沟涨,謹(jǐn)慎使用輪循或者sleep函數(shù)异吻。
  • 界面開(kāi)發(fā)中诀浪,耗時(shí)的業(yè)務(wù)代碼不要放在UI線程中執(zhí)行延都,使用單獨(dú)的線程去異步處理耗時(shí)業(yè)務(wù)晰房,提高界面響應(yīng)速度射沟。
  • 經(jīng)常重構(gòu)验夯、優(yōu)化代碼結(jié)構(gòu)摔刁。優(yōu)化算法或者架構(gòu)共屈,從設(shè)計(jì)層面進(jìn)行性能的優(yōu)化。

二借宵、計(jì)算機(jī)網(wǎng)絡(luò)編程

  1. select矾削、poll怔软、epoll的區(qū)別

select、poll括改、epoll是多路復(fù)用主要用到的三種技術(shù)家坎,主要區(qū)別如下:

① 支持一個(gè)進(jìn)程所能打開(kāi)的最大連接數(shù)
select
? 單個(gè)進(jìn)程所能打開(kāi)的最大連接數(shù)有FD_SETSIZE宏定義虱疏,其大小是32個(gè)整數(shù)的大小(在32位的機(jī)器上对粪,大小就是3232著拭,同理64位機(jī)器上FD_SETSIZE為3264)牍帚,當(dāng)然我們可以對(duì)進(jìn)行修改暗赶,然后重新編譯內(nèi)核肃叶,但是性能可能會(huì)受到影響因惭,這需要進(jìn)一步的測(cè)試详幽。
poll
? poll本質(zhì)上和select沒(méi)有區(qū)別唇聘,但是它沒(méi)有最大連接數(shù)的限制,原因是它是基于鏈表來(lái)存儲(chǔ)的剥险。
epoll
? 雖然連接數(shù)有上限表制,但是很大控乾,1G內(nèi)存的機(jī)器上可以打開(kāi)10萬(wàn)左右的連接蜕衡,2G內(nèi)存的機(jī)器可以打開(kāi)20萬(wàn)左右的連接慨仿。

② FD劇增后帶來(lái)的IO效率問(wèn)題
select
? 因?yàn)槊看握{(diào)用時(shí)都會(huì)對(duì)連接進(jìn)行線性遍歷镰吆,所以隨著FD的增加會(huì)造成遍歷速度慢的“線性下降性能問(wèn)題”。
poll
? 同上摧找。
epoll
? 因?yàn)閑poll內(nèi)核中實(shí)現(xiàn)是根據(jù)每個(gè)fd上的callback函數(shù)來(lái)實(shí)現(xiàn)的慰于,只有活躍的socket才會(huì)主動(dòng)調(diào)用callback唤衫,所以在活躍socket較少的情況下佳励,使用epoll沒(méi)有前面兩者的線性下降的性能問(wèn)題,但是所有socket都很活躍的情況下妙黍,可能會(huì)有性能問(wèn)題拭嫁。

③ 消息傳遞方式
select
? 內(nèi)核需要將消息傳遞到用戶空間抓于,都需要內(nèi)核拷貝動(dòng)作捉撮。
poll
? 同上。
epoll
? epoll通過(guò)內(nèi)核和用戶空間共享一塊內(nèi)存來(lái)實(shí)現(xiàn)的肉康。

  1. TCP和UDP的區(qū)別
  • TCP是面向連接的吼和,UDP是無(wú)連接的
  • TCP是可靠的骑素,UDP是不可靠的
  • TCP是面向字節(jié)流的砂豌,UDP是面向數(shù)據(jù)報(bào)文的
  • TCP只支持點(diǎn)對(duì)點(diǎn)通信,UDP支持一對(duì)一塔粒,一對(duì)多卒茬,多對(duì)多
  • TCP報(bào)文首部20個(gè)字節(jié)咖熟,UDP首部8個(gè)字節(jié)
  • TCP有擁塞控制機(jī)制馍管,UDP沒(méi)有
  • TCP協(xié)議下雙方發(fā)送接受緩沖區(qū)都有,UDP并無(wú)實(shí)際意義上的發(fā)送緩沖區(qū)捌锭,但是存在接受緩沖區(qū)
  1. TCP三次握手

① 第一次握手
客戶端給服務(wù)器發(fā)送一個(gè)SYN段(在 TCP 標(biāo)頭中 SYN 位字段為 1 的 TCP/IP 數(shù)據(jù)包), 該段中也包含客戶端的初始序列號(hào)(Sequence number = J)观谦。

② 第二次握手
服務(wù)器返回客戶端 SYN +ACK 段(在 TCP 標(biāo)頭中SYN和ACK位字段都為 1 的 TCP/IP 數(shù)據(jù)包)豁状, 該段中包含服務(wù)器的初始序列號(hào)(Sequence number = K);同時(shí)使 Acknowledgment number = J + 1來(lái)表示確認(rèn)已收到客戶端的 SYN段(Sequence number = J)夭禽。

③ 第三次握手
客戶端給服務(wù)器響應(yīng)一個(gè)ACK段(在 TCP 標(biāo)頭中 ACK 位字段為 1 的 TCP/IP 數(shù)據(jù)包), 該段中使 Acknowledgment number = K + 1來(lái)表示確認(rèn)已收到服務(wù)器的 SYN段(Sequence number = K)驻粟。

  1. 三次握手的原因

? 為了實(shí)現(xiàn)可靠數(shù)據(jù)傳輸凶异,TCP 協(xié)議的通信雙方剩彬,都必須維護(hù)一個(gè)序列號(hào),以標(biāo)識(shí)發(fā)送出去的數(shù)據(jù)包中沃饶,哪些是已經(jīng)被對(duì)方收到的糊肤。三次握手的過(guò)程即是通信雙方相互告知序列號(hào)起始值氓鄙,并確認(rèn)對(duì)方已經(jīng)收到了序列號(hào)起始值的必經(jīng)步驟抖拦。

  1. TCP四次揮手

① 第一次揮手: Client端發(fā)起揮手請(qǐng)求态罪,向Server端發(fā)送標(biāo)志位是FIN報(bào)文段,設(shè)置序列號(hào)seq绩聘,此時(shí)君纫,Client端進(jìn)入FIN_WAIT_1狀態(tài)芹彬,這表示Client端沒(méi)有數(shù)據(jù)要發(fā)送給Server端了舒帮。

② 第二次揮手:Server端收到了Client端發(fā)送的FIN報(bào)文段,向Client端返回一個(gè)標(biāo)志位是ACK的報(bào)文段肢执,ack設(shè)為seq加1预茄,Client端進(jìn)入FIN_WAIT_2狀態(tài)侦厚,Server端告訴Client端刨沦,我確認(rèn)并同意你的關(guān)閉請(qǐng)求想诅。

③ 第三次揮手: Server端向Client端發(fā)送標(biāo)志位是FIN的報(bào)文段,請(qǐng)求關(guān)閉連接篮灼,同時(shí)Client端進(jìn)入LAST_ACK狀態(tài)诅诱。

④ 第四次揮手 : Client端收到Server端發(fā)送的FIN報(bào)文段晌坤,向Server端發(fā)送標(biāo)志位是ACK的報(bào)文段骤菠,然后Client端進(jìn)入TIME_WAIT狀態(tài)商乎。Server端收到Client端的ACK報(bào)文段后,關(guān)閉連接鲜戒。此時(shí)翔烁,Client端等待2MSL的時(shí)間后依然沒(méi)有收到回復(fù)疼鸟,則證明Server端已正常關(guān)閉,Client端也關(guān)閉連接粹庞。

  1. 四次揮手的原因

其實(shí)是客戶端和服務(wù)端的兩次揮手庞溜,也就是客戶端和服務(wù)端分別釋放連接的過(guò)程流码。客戶端在發(fā)送完最后一次確認(rèn)之后赏胚,還要等待2MSL的時(shí)間觉阅。有兩個(gè)原因: 一是為了讓B能夠按照正常步驟進(jìn)入CLOSED狀態(tài)典勇,二是為了防止已經(jīng)失效的請(qǐng)求連接報(bào)文出現(xiàn)在下次連接中叮趴。

① 由于客戶端最后一個(gè)ACK可能會(huì)丟失眯亦,這樣B就無(wú)法正常進(jìn)入CLOSED狀態(tài)妻率。于是B會(huì)重傳請(qǐng)求釋放的報(bào)文,而此時(shí)A如果已經(jīng)關(guān)閉了走净,那就收不到B的重傳請(qǐng)求伏伯,就會(huì)導(dǎo)致B不能正常釋放。而如果A還在等待時(shí)間內(nèi)炸枣,就會(huì)收到B的重傳抛虏,然后進(jìn)行應(yīng)答,這樣B就可以進(jìn)入CLOSED狀態(tài)了背伴。

② 在這2MSL等待時(shí)間里面峰髓,本次連接的所有的報(bào)文都已經(jīng)從網(wǎng)絡(luò)中消失携兵,從而不會(huì)出現(xiàn)在下次連接中。

  1. 編寫(xiě)socket套接字的步驟
  • 服務(wù)器端程序的編寫(xiě)步驟
    ① 調(diào)用socket()函數(shù)創(chuàng)建一個(gè)用于通信的套接字静檬。
    ② 第二步:給已經(jīng)創(chuàng)建的套接字綁定一個(gè)端口號(hào)拂檩,這一般通過(guò)設(shè)置網(wǎng)絡(luò)套接口地址和調(diào)用bind()函數(shù)來(lái)實(shí)現(xiàn)稻励。
    ③ 調(diào)用listen()函數(shù)使套接字成為一個(gè)監(jiān)聽(tīng)套接字愈涩。
    ④ 調(diào)用accept()函數(shù)來(lái)接受客戶端的連接履婉,這是就可以和客戶端通信了谐鼎。
    ⑤ 處理客戶端的連接請(qǐng)求。
    ⑥ 終止連接身害。

  • 客戶端程序編寫(xiě)步驟
    ① 調(diào)用socket()函數(shù)創(chuàng)建一個(gè)用于通信的套接字塌鸯。
    ② 通過(guò)設(shè)置套接字地址結(jié)構(gòu)丙猬,說(shuō)明客戶端與之通信的服務(wù)器的IP地址和端口號(hào)茧球。
    ③ 調(diào)用connect()函數(shù)來(lái)建立與服務(wù)器的連接。
    ④ 調(diào)用讀寫(xiě)函數(shù)發(fā)送或者接收數(shù)據(jù)弹灭。
    ⑤ 終止連接穷吮。

三捡鱼、操作系統(tǒng)

  1. 如何不用sizeof()判斷系統(tǒng)是16位還是32位?
    可通過(guò)內(nèi)存地址地址長(zhǎng)度判斷驾诈,定義一個(gè)指針變量伟墙,通過(guò)打印其地址即可判斷戳葵。

  2. 進(jìn)程和線程間的通信方式
    匿名管道(pipe)拱烁、高級(jí)管道(popen)、有名管道(fifo)邦投、消息隊(duì)列志衣、信號(hào)量念脯、信號(hào)(sinal)、共享內(nèi)存吉懊、套接字(socket)借嗽。

  3. 線程安全和線程不安全
    線程安全指支持多線程訪問(wèn)恶导,多線程訪問(wèn)時(shí)不會(huì)導(dǎo)致共享數(shù)據(jù)污染甲锡。反之羽戒,為線程不安全易稠。

  4. 死鎖產(chǎn)生的原因和死鎖的條件

  • 死鎖的定義
    ? 兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過(guò)程中驶社,由于競(jìng)爭(zhēng)資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象亡电,若無(wú)外力作用份乒,它們都將無(wú)法推進(jìn)下去或辖。

  • 死鎖的產(chǎn)生原因
    通常是源于多個(gè)進(jìn)程對(duì)資源的爭(zhēng)奪枣接,不僅對(duì)不可搶占資源進(jìn)行爭(zhēng)奪或引起死鎖但惶,而且對(duì)可消耗資源進(jìn)行爭(zhēng)奪也會(huì)引起死鎖⊙羯叮總結(jié)如下:
    ① 系統(tǒng)資源不足捌省;
    ② 進(jìn)程運(yùn)行推進(jìn)的順序不當(dāng)纲缓;
    ③ 資源分配不當(dāng)祝高;

  • 死鎖產(chǎn)生的必要條件
    ① 互斥條件:
    進(jìn)程在運(yùn)行中對(duì)資源進(jìn)行排他性使用工闺,即一個(gè)資源僅能被一個(gè)進(jìn)程使用陆蟆,此時(shí)其他進(jìn)程請(qǐng)求資源時(shí)雷厂,只能等待其釋放。
    ② 請(qǐng)求與保持條件:
    某進(jìn)程已經(jīng)保持了一個(gè)資源叠殷,但又請(qǐng)求另一個(gè)資源改鲫,若該資源被其他進(jìn)程占有,此時(shí)請(qǐng)求阻塞林束,且對(duì)已經(jīng)占有的資源不釋放像棘;
    ③ 不可搶占條件:
    進(jìn)程獲得的資源在未使用完時(shí)不可被搶占壶冒,只能在進(jìn)程使用完時(shí)自己釋放缕题;
    ④ 循環(huán)等待條件
    發(fā)生死鎖時(shí),必然存在這樣一個(gè)循環(huán)胖腾,一個(gè)進(jìn)程p1等待p2占有的資源進(jìn)程p2等待p3占有的資源...進(jìn)程pn等待p1占有的資源烟零。

  • 死鎖的處理方法
    ① 預(yù)防死鎖:事先預(yù)防策略,容易實(shí)現(xiàn)胸嘁,通過(guò)實(shí)現(xiàn)設(shè)置限制瓶摆,破壞產(chǎn)生死鎖的四個(gè)條件之一。(如對(duì)資源采用按序分配策略)
    ② 避免死鎖:事先預(yù)防策略性宏,在資源的動(dòng)態(tài)分配過(guò)程中群井,用某些方法防止系統(tǒng)禁圖不安全狀態(tài)。常見(jiàn)的方法有銀行家算法毫胜。
    ③ 檢測(cè)死鎖:通過(guò)檢測(cè)機(jī)構(gòu)等及時(shí)檢測(cè)出死鎖书斜,采取適當(dāng)措施诬辈,把進(jìn)程從死鎖中解脫。
    ④ 解除死鎖:檢測(cè)出死鎖后荐吉,采取措施解決焙糟。比如剝奪資源,撤銷(xiāo)進(jìn)程样屠。
    這四種方法對(duì)死鎖的防范逐漸減弱穿撮,但對(duì)應(yīng)的是資源利用率的提高。

  1. 如何采用單線程處理高并發(fā)
    采用非阻塞,異步編程的思想痪欲。
    ① IO多路復(fù)用技術(shù)
    ② 采用事件驅(qū)動(dòng)模型悦穿,基于異步回調(diào)來(lái)處理事件

  2. 線程的狀態(tài)
    運(yùn)行期、掛起业踢、死亡栗柒、正常退出、和線程阻塞知举。

  3. 進(jìn)程的狀態(tài)
    ① 運(yùn)行(running)態(tài):進(jìn)程占有處理器正在運(yùn)行瞬沦。
    ② 就緒(ready)態(tài):進(jìn)程具備運(yùn)行條件,等待系統(tǒng)分配處理器以便運(yùn)行雇锡。
    ③ 等待(wait)態(tài):又稱為阻塞(blocked)態(tài)或睡眠(sleep)態(tài)逛钻,指進(jìn)程不具備運(yùn)行條件,正在等待某個(gè)事件的完成锰提。

  4. 系統(tǒng)調(diào)用brk和mmap

從操作系統(tǒng)角度來(lái)看绣的,進(jìn)程分配內(nèi)存有兩種方式,分別由兩個(gè)系統(tǒng)調(diào)用完成:brk和mmap(不考慮共享內(nèi)存)。

  • brk是將數(shù)據(jù)段(.data)的最高地址指針_edata往高地址推芭概;
  • mmap是在進(jìn)程的虛擬地址空間中(堆和棧中間,稱為文件映射區(qū)域的地方)找一塊空閑的虛擬內(nèi)存踢故。

這兩種方式分配的都是虛擬內(nèi)存惹苗,沒(méi)有分配物理內(nèi)存。在第一次訪問(wèn)已分配的虛擬地址空間的時(shí)候淋纲,發(fā)生缺頁(yè)中斷院究,操作系統(tǒng)負(fù)責(zé)分配物理內(nèi)存本涕,然后建立虛擬內(nèi)存和物理內(nèi)存之間的映射關(guān)系伙窃。

  1. 進(jìn)程和線程的區(qū)別
    ① 地址空間
    線程共享本進(jìn)程的地址空間菩颖,而進(jìn)程之間是獨(dú)立的地址空間。
    ② 資源
    線程共享本進(jìn)程的資源如內(nèi)存为障、I/O晦闰、cpu等,不利于資源的管理和保護(hù)鳍怨,而進(jìn)程之間的資源是獨(dú)立的呻右,能很好的進(jìn)行資源管理和保護(hù)。
    ③ 健壯性
    多進(jìn)程要比多線程健壯京景,一個(gè)進(jìn)程崩潰后窿冯,在保護(hù)模式下不會(huì)對(duì)其他進(jìn)程產(chǎn)生影響,但是一個(gè)線程崩潰整個(gè)進(jìn)程都死掉确徙。
    ④ 執(zhí)行過(guò)程
    每個(gè)獨(dú)立的進(jìn)程有一個(gè)程序運(yùn)行的入口醒串、順序執(zhí)行序列和程序入口,執(zhí)行開(kāi)銷(xiāo)大鄙皇。
    但是線程不能獨(dú)立執(zhí)行芜赌,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個(gè)線程執(zhí)行控制伴逸,執(zhí)行開(kāi)銷(xiāo)小缠沈。
    ⑤ 可并發(fā)性
    兩者均可并發(fā)執(zhí)行。
    ⑥ 切換時(shí)
    進(jìn)程切換時(shí)错蝴,消耗的資源大洲愤,效率高。所以涉及到頻繁的切換時(shí)顷锰,使用線程要好于進(jìn)程柬赐。同樣如果要求同時(shí)進(jìn)行并且又要共享某些變量的并發(fā)操作肛宋,只能用線程不能用進(jìn)程。
    ⑦ 其他
    線程是處理器調(diào)度的基本單位沉帮,但是進(jìn)程不是馅精。

  2. 工作常用到的Linux命令
    find、grep压彭、ps、top询一、ls(比較簡(jiǎn)單健蕊,不展開(kāi))

  3. gdb
    參考網(wǎng)上gdb常用的調(diào)試手法。

  4. gcc/g++
    C和C++的編譯工具嫡锌。

  5. 什么是虛擬內(nèi)存
    《操作系統(tǒng)》:虛擬存儲(chǔ)技術(shù)的基本思想時(shí)利用大容量外存來(lái)擴(kuò)充內(nèi)存,產(chǎn)生一個(gè)比有限的實(shí)際內(nèi)存空間大得多的歌懒、邏輯的虛擬空間,簡(jiǎn)稱虛存躲庄,以便能夠有效地支持多道程序系統(tǒng)的實(shí)現(xiàn)和大型程序運(yùn)行的需要,從而增強(qiáng)系統(tǒng)的處理能力倔监。

  1. 常見(jiàn)的內(nèi)存管理機(jī)制

簡(jiǎn)單的分為連續(xù)分配管理方式和非連續(xù)分配管理方式這兩種浩习。連續(xù)分配管理方式是指為一個(gè)用戶程序分配一個(gè)連續(xù)的內(nèi)存空間洽蛀,比如塊式管理郊供。非連續(xù)分配管理方式允許一個(gè)程序內(nèi)存分散,比如頁(yè)式管理疯淫、段式管理和段頁(yè)式管理峡竣。

  • 塊式管理
    遠(yuǎn)古時(shí)代的計(jì)算機(jī)操作系統(tǒng)的內(nèi)存管理方式,將內(nèi)存分為幾個(gè)固定大小的塊类浪,每個(gè)塊只包含一個(gè)進(jìn)程,如果程序運(yùn)行需要內(nèi)存力细,操作系統(tǒng)就給它分配一塊眠蚂,如果程序運(yùn)行只需要很小的空間,則分配的這塊內(nèi)存很大一部分就浪費(fèi)了云稚,這些在每個(gè)塊中未被利用的空間静陈,我們稱為碎片。

  • 頁(yè)式管理
    把主存分為大小相等且固定的一頁(yè)一頁(yè)的形式崩泡,頁(yè)比較小,相對(duì)于塊式管理的劃分力度更大谒所,提高了內(nèi)存利用率劣领,減少了碎片尖淘。頁(yè)式管理通過(guò)頁(yè)表對(duì)應(yīng)邏輯地址和物理地址。

  • 段式管理
    頁(yè)式管理雖然提高了內(nèi)存利用率,但是其中的頁(yè)沒(méi)有任何實(shí)際意義肄鸽,段式管理把主存分為一段一段 ,每一段的空間又比一頁(yè)的空間小很多。但是段有實(shí)際意義汛骂,段式管理通過(guò)段表對(duì)應(yīng)邏輯地址和物理地址淑掌。

  • 段頁(yè)式管理
    段頁(yè)式管理機(jī)制結(jié)合了段式管理和頁(yè)式管理的優(yōu)點(diǎn),就是把主存分為若干段担敌,每個(gè)段又分為若干頁(yè)桃犬,也就是說(shuō)段頁(yè)式管理機(jī)制中段和段之間以及段的內(nèi)部都是離散的土匀。

  1. 大端和小端就轧,用C++代碼怎么確定
  • 指針?lè)?/li>
int JudgeSystem(void) {
    int a = 1;
    char *p = (char *)&a;
 
    // 如果是小端則返回 1,如果是大端則返回 0
    return *p;
}
  • 聯(lián)合體法
int JudgeSystem(void) {
    union {
        char c;
        int i;
    } un; // 匿名聯(lián)合體 un
 
    un.i = 1;
 
    // 如果是小端則返回 1携丁,如果是大端則返回 0
    return un.c;
}

四、數(shù)據(jù)結(jié)構(gòu)及算法

  1. 幾種常見(jiàn)的排序算法
    ① 冒泡排序
    ② 選擇排序
    ③ 插入排序
    ④ 希爾排序
    ⑤ 快速排序
    ⑥ 歸并排序
    ⑦ 堆排序

  2. 鏈表的特點(diǎn)和操作

  • 特點(diǎn)
    ① 采用動(dòng)態(tài)存儲(chǔ)分配,不會(huì)造成內(nèi)存浪費(fèi)和溢出宠互。
    ② 鏈表執(zhí)行插入和刪除操作十分方便椭坚,修改指針即可予跌,不需要移動(dòng)大量元素。
  • 常見(jiàn)操作
    ① 創(chuàng)建
    ② 插入
    ③ 修改
    ④ 查找
    ⑤ 刪除
  1. 常見(jiàn)的查找算法
    ① 順序查找
    ② 二分查找
    ③ 插值查找
    ④ 斐波那契查找
    ⑤ 樹(shù)表查找
    ⑥ 分塊查找
    ⑦ 哈希查找

  2. 如何判斷鏈表是否為環(huán)形

通過(guò)快慢指針善茎。慢指針每次走1步券册,快指針每次走2步。當(dāng)快慢指針相遇垂涯,說(shuō)明鏈表為循環(huán)鏈表烁焙。

bool IsRingList(SNode* pHead)
{
    bool ret = false;
    SNode *pSlow = pHead, *pFast = pHead;

    while(pFast && pFast->next)
    {
        pSlow = pSlow->next;
        pFast = pFast->next->next;

        if (pSlow == pFast) {
            return true;
        }
    }
    
    return ret;
}
  1. 計(jì)算環(huán)形鏈表的長(zhǎng)度

通過(guò)快慢指針鞠苟。慢指針每次走1步鹦倚,快指針每次走2步,兩者速度差為1步夺颤。 當(dāng)兩指針相遇時(shí)嵌洼,快指針比慢指針多走1圈。

int GetRingListLength(SNode* pHead)
{
    int length = 0;
    SNode *pSlow = pHead, *pFast = pHead;
 
    while(pFast && pFast->next)
    {
        pSlow = pSlow->next;
        pFast = pFast->next->next;
        length++;

        if (pSlow == pFast) {
            break;
        }
    }

    if (pSlow != pFast)
    {
        length = 0;
        printf("It is not ring list.\n");
    }

    return length;
}
  1. 查找單鏈表倒數(shù)第n個(gè)節(jié)點(diǎn)

通過(guò)快慢指針崭倘,快指針先走n步坞淮,隨后慢指針與快指針同步走,當(dāng)快指針到達(dá)鏈表尾部時(shí)阐滩,慢指針即為倒數(shù)第n個(gè)節(jié)點(diǎn)凡简。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市后频,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌消请,老刑警劉巖昭殉,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件越走,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡护锤,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)饥追,“玉大人狸臣,你說(shuō)我怎么就攤上這事〔矗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵懂拾,是天一觀的道長(zhǎng)煤禽。 經(jīng)常有香客問(wèn)我,道長(zhǎng)岖赋,這世上最難降的妖魔是什么杭抠? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任沿猜,我火速辦了婚禮,結(jié)果婚禮上蛮原,老公的妹妹穿的比我還像新娘花嘶。我一直安慰自己,他們只是感情好凶赁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布致板。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瘦馍,一...
    開(kāi)封第一講書(shū)人閱讀 51,287評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音底瓣,去河邊找鬼。 笑死村视,一個(gè)胖子當(dāng)著我的面吹牛官套,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼奶赔,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼惋嚎!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起站刑,我...
    開(kāi)封第一講書(shū)人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤另伍,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后绞旅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體摆尝,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年因悲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了堕汞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡晃琳,死狀恐怖讯检,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卫旱,我是刑警寧澤人灼,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站顾翼,受9級(jí)特大地震影響投放,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜适贸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一灸芳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧取逾,春花似錦、人聲如沸苹支。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)债蜜。三九已至晴埂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間寻定,已是汗流浹背儒洛。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留狼速,地道東北人琅锻。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親恼蓬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子惊完,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容