C++后台騰訊實習面試經歷


鏈接

 

1
2
3
4
時間: 2018 4 16
崗位:C/C++后台開發(Linux)
BG:WXG
關於我:本科大三 預計 2019 年畢業

一面(普通技術面)

過程:遞交簡歷 -> 手撕代碼 -> 開始面試 -> 結束

耗時:about 1 hour

手撕代碼:一顆二叉搜索樹,找出樹中的第k大節點

拿到題目之后沒有任何思考,想用中序遍歷然后把遍歷結果放到一個容量為k的隊列中(基本操作)。但是為什么順手就寫下vector???面試官看見我這么快下筆之后看了看我寫的東西,然后提醒說不能轉存。思考了不到30秒,有點慌,然后迅速冷靜下來。第二個思路:利用遞歸中序遍歷把二叉搜索樹轉成一個雙向鏈表,然后遍歷鏈表k步找到第k大節點或者返回NULL表示k無效。中途寫的時候,面試官看了看我寫的代碼,然后問我思路,然后給他介紹了一遍。快寫完的時候,他說其實我只是想考考你中序遍歷,我說不能轉存但是還是可以用棧的...(那我用隊列有錯嗎...)

開始面試:

  1. fork過程

    Q:介紹一下fork的流程

    A:從源碼來看,fork就是簡單的把父進程的幾乎所有東西都拷貝一份,比如會復制父進程的地址空間、已打開文件描述符、命名空間啊這些之類的...然后修改一些標志讓自己與父進程變得不一樣

    Q:棧和堆會拷貝嗎

    A:emmm...會

    Q:在復制之前會做些什么呢

    A:emmm...(思考半天,沒做什么呀...)

    Q:表示進程的那個結構體呢,會復制嗎

    A:task_struct嗎?對對對,在這之前會先從slab中分配一個PCB...

    FIXME:copy-on-write沒有表達出來

  2. fork、vfork以及clone的區別

    Q:介紹一下fork、vfork還有clone的區別

    A:從源碼來分析,它們都用來創建linux輕量級進程的,vfork與fork的區別是,vfork共享父進程的地址空間,vfork之后父進程會讓自進程先運行,因為vfork主要用於為了讓子進程exec,exec之后子進程會用新程序的數據將內存重新刷一遍,這樣它就有了自己的地址空間。子進程exec之后,會向父進程發送信號,這個時候父進程就可以開始運行了,如果子進程修改了父進程地址空間的話,父進程喚醒的時候就會發現自己的數據被改了,完整性丟失,所以這是不安全的。clone的話呢,它提供選項,讓你自己選擇每次復制哪些東西,但是它調用的還是do_fork好像...

  3. 僵屍進程

    Q:介紹一下僵屍進程吧

    A:僵屍進程就是死掉之后還沒有被父進程wait的進程,它們在運行結束之后PCB這些資源還沒有被釋放,等待父進程wait它們獲得它們的狀態。如果父進程不wait的話,僵屍進程多了,未被釋放的資源就很多,這個時候系統性能就會受到影響。如果父進程早死了的話,子進程就會被托管到pid為1的進程,以前是init現在是systemd好像,它會定時wait掉所有死了的子進程

    Q:怎樣避免僵屍進程呢

    A:單獨一個線程wait子進程,或者emmm...有兩個信號,一個SIGCHLD、一個SIGCLD,設置這兩個信號的處理方式為忽略,它們告訴內核,不關心子進程結束的狀態所以當子進程終止的時候直接釋放所有資源就行。它們的區別是SIGCLD在安裝完信號處理函數的時候還會檢查是否已經存在結束的子進程,如果有就調用信號處理函數,而SIGCHLD不會,也就是可能會丟掉已經有子進程已經結束這個事實

  4. 從匯編層去解釋一下引用

    Q:從匯編去解釋一下引用

    A:我們先來看看左值引用吧(畫圖示意),左值引用封裝了一個指針,指針指向被引用的對象,每次使用這個引用就是解引用這個被封裝的指針。右值引用的話,底層是將原來的對象進行了一份內存拷貝,然后封裝了對這個拷貝的指針。因為是拷貝,所以實際上右值引用其實也是左值,emmm...STL里面有一個forkward函數,它的作用就是用來進行右值引用的類型恢復...

  5. 驚群效應,如何避免

    Q:驚群效應了解嗎

    A:網絡泛洪嗎(搞錯了概念)

    Q:不是,比如說一個資源有效的時候會通知所有用戶(其實已經把驚群效應的現象給講出來了...)

    A:我先舉個例子吧,linux內核中的等待隊列,等待隊列中的等待節點有兩種狀態,一種是互斥等待,一種是非互斥等待。如果某個事件一發生,會喚醒對應的等待隊列中的所有非互斥等待節點,而如果是互斥等待節點的話,可以選擇喚醒所有節點,也可以選擇喚醒指定個節點。Pthread線程庫里面也有一個很好的例子,pthread_cond_signal與pthread_cond_broadcast,signal只通知一個信號量,而broadcast會通知所有信號量。但是有時候就緒的事件只能滿足一個用戶,如果選擇廣播的話就會通知所有用戶,然后最終只有一個用戶可以得到滿足,其他用戶還是被阻塞導致不必要的性能浪費

    Q:那你如何解決驚群呢

    A:...(寫了一段偽代碼,大致是加鎖、條件判斷...)

  6. 中斷的作用

    Q:中斷的作用是什么

    A:...(從cpu去分析的中斷,什么特權級呀、中斷門啊、陷阱門呀、任務門呀之類的都講了一遍)

    Q:你這是從太底層很細節的方面去分析的中斷,但是我想從宏觀的方面去了解一下

    A:...(語塞)

    Q:比如說任務調度?

    A:哦,時間中斷嗎,如果沒有時間中斷的話,多任務操作系統就不能及時調度,惡意程序就可能霸占處理器,然后就把操作系統給弄死了

    Q:也不一定會弄死呀,你看批處理操作系統呢

    A:對對對...

  7. tcp的連接關閉

    Q:講一下tcp關閉連接的過程

    A:四路揮手嗎,我畫個圖吧

    Q:好

    A:我用socket描述這個過程吧(講了每一個函數操作之后的包發送情況還有狀態變化,之前說被關閉方收到FIN之后會變成CLOSE_WAIT狀態,他說不是,后來他發現是的...)

    A:....(解釋中),這個時候主動關閉方的狀態變成TIME_WAIT...(被打斷,開始提問下一個問題)

  8. TIME_WAIT

    Q:TIME_WAIT的話那你來解釋一下它的作用吧

    A:...(兩個作用)

    Q:如何避免呢

    A:...(我講了兩個,socket選項和線程池)

    Q:假設現在系統中有很多處於TIME_WAIT的連接,這個時候你會怎么做

    A:有一個socket選項,可以進行地址重用,我們可以可重用這些處於TIME_WAIT狀態的連接的地址,沒有問題的

  9. 如果網絡延遲很高,但是又沒有發生丟包,利用tcp會使吞吐量下降,該如何解決呢

    Q:tcp滑動窗口了解嗎

    A:了解(剛想開始介紹就被打斷)

    Q:ok,那tcp的擁塞控制呢

    A:也知道

    Q:好,假設現在網絡延遲很高,但是又沒有發生丟包,這個時候用tcp進行傳輸你覺得速率怎么樣

    A:不是很好

    Q:那你會怎么解決呢

    A:如果網絡延遲很高,但是實際上網絡沒有發生丟包的話,tcp的擁塞控制可能會進行快重傳使發送速率下降,你是覺得瓶頸出在快重傳是吧

    Q:嗯,也就是我想避免擁塞控制

    A:(哇突然問題清楚了...)從應用層封裝udp協議或者使用raw socket直接封裝ip數據報

    Q:...網絡延遲還沒高到要封裝ip數據報的地步

  10. Ddos攻擊原理

    Q:DDos攻擊的原理介紹一下

    A:emmm...listen有一個隊列,處理連接請求。在收到匿名IP發過來的SYN之后,會在listen隊列中存放一個記錄,但是隊列容量是有限的,當這樣的惡意請求過多的時候,listen隊列里就塞滿了這些無效的連接請求,然后裝不下更多的連接記錄了,所以就拒絕其他請求了

    Q:嗯,大致是這個意思

  11. 如何在共享內存上使用stl標准庫

    Q:假設我現在開辟了一片共享內存,然后我想在這塊共享內存上使用stl庫,該怎么做呢

    A:假設兩個進程A和B,它們使用相同的共享庫,(畫了一下進程的內存布局)加載器會自動的幫它們把共享庫映射到共享內存呀,我們只要在鏈接的時候指定共享鏈接就行了

    Q:不是,你理解錯我的意思了,比如說我使用vector,我想要它的元素全部在共享內存上,就算是新添加的元素也是被分配在共享內存上

    A:emmm...讓我想一想...(把vector模板聲明寫了出來,指着vector的模板參數Alloc),我們可以重寫一個allocator,把共享內存划分給它,用這些共享內存實現一個內存池,讓allocator來對它進行管理

    Q:重寫一個allocator嗎

    A:對

  12. 數據庫引擎

    Q:數據庫引擎了解嗎

    A:不是很了解

  13. 數據庫三個重要范式

    Q:數據庫的三個范式你知道嗎

    A:第一二三范式嗎

    Q:對

    A:...(大致介紹了一下)現在還有時間嗎,要不要我給你講個例子

    Q:...(看了看時間)例子就不用了

  14. 網絡層、數據鏈路層、傳輸層的設備有哪些

    Q:數據鏈路層的設備有哪些

    A:網橋是的,集線器...emmm集線器是物理層的,還有就不清楚了,就只知道網橋這一個

    Q:網絡層呢

    A:路由器

    Q:傳輸層呢

    A:OSI七層模型中的傳輸層、會話層還有應用層在Tcp/Ip五層結構里面統歸於應用層,這個時候不就只有軟件了嗎

    Q:對呀,軟件也算是一種設備呀

  15. 網絡層、傳輸層協議有哪些

    Q:網絡層有哪些協議

    A:ip、icmp、igmp就這三個主要的了,對了,還有一個rip

    Q:傳輸層呢

    A:傳輸層的話主要就tcp、udp兩種

  16. 網絡層、數據鏈路層、傳輸層使用的尋址地址分別是什么

    Q:網絡層用什么尋址

    A:ip地址

    Q:數據鏈路層呢

    A:物理層是mac...emmm...不是數據鏈路層是mac

    Q:傳輸層呢

    A:(在紙上寫下{ ip: port })這個

    Q:傳輸層有ip嗎

    A:(圈出port)那就是這個...

  17. 內存分配原理

    Q:介紹一下內存分配原理

    A:...(把堆的內存(《深入理解計算機系統》中有一章具體介紹)講了一遍,再仔細描述了一下伙伴系統的具體實現)

  18. 多態的實現原理

    Q:把C++多態的實現講一下吧

    A:...(從虛表表、虛函數表、虛函數表指針去具體介紹,然后介紹了構造析構過程中虛函數表指針的變化過程,然后從這些變化過程去解釋語言級別的現象...)

  19. AVL樹、B+樹、紅黑樹

    Q:介紹一下平衡二叉樹、B+樹、紅黑樹

    A:平衡二叉樹每個節點的兩顆子樹高度相差小於2,所以也叫高度平衡樹。紅黑樹根據黑高來實現每個節點的左右兩顆子樹高度相差低於2倍,雖然紅黑樹的平衡性沒有AVL樹嚴格,但是研究好像表明紅黑樹性能更好而且這個平衡度已經足夠了。B+樹的話不是很清楚,但是知道它在數據庫里用的多,還有只有它的葉節點包含實際數據,其他節點只含有鍵

  20. gcc選項

    Q:gcc選項知道哪些

    A:-O優化選項、-W加強警告...還有分階段編譯:-E預編譯生成.i文件,-S預編譯+編譯生成.s文件,-c生成.o文件,-o指定輸出文件,-l指定鏈接庫,差不多用得多的就這些了

    Q:加調試信息

    A:最簡單的,比如說內核調試有個pritnk...

    Q:不是不是,我是說gcc在編譯的時候給程序加調試信息用什么選項

    A:-gstabs

    Q:多線程編譯呢

    A:-j(現在回想起來,發現-j選項是make的選項,gcc不支持多線程編譯...)

  21. poll和epoll的區別

    Q:poll和epoll了解嗎

    A:從內核源碼來分析吧,誒不用介紹select嗎...算了,其實select跟poll是差不多的,復用了很多代碼,只是記錄監聽events的數據結構不一樣...(先介紹了select,然后講了一下與poll的區別)。epoll的話,在類unix系統中好像只有linux有,epoll把epoll實例創建、events增刪改還有events輪詢都分開了,這樣的話epoll實例就可以被同一個進程中的所有線程共享。epoll跟poll一樣,使用鏈表節點記錄監聽events,但是呢它有三個鏈表型結構(就緒鏈表、輔助鏈表、紅黑樹),首先想要監聽的events的節點被放到紅黑樹里,這樣可以加快events節點的訪問。events就緒之后會被掛載到就緒鏈表里去,當epoll_wait從內核空間向用戶空間寫出就緒events的時候,會遍歷就緒鏈表,同時這個時候可能還會發生新的就緒events,這個時候已就緒的events不再添加到就緒鏈表里去,而是使用輔助鏈表...

  22. epoll中ET模式與LT模式的區別

    Q:再講一下epoll的ET模式和LT模式

    A:在epoll_wait調用中,epoll會遍歷就緒隊列里的每一個events節點,然后通過文件的poll方法再次獲取事件的最新狀態revents,然后把該events節點從就緒鏈表中刪除。當revents中包含我們關心的事件events的話,LT模式還會把該節點重新加入到就緒隊列里,而ET模式也就是edge邊界模式不會。這么做有什么影響呢,emmm...讓我舉個例子,假設我們監聽一個管道可讀,當事件就緒之后,我們只讀了部分內容,還有部分內容沒有讀。當我們再次epoll_wait的時候,對LT模式來說,就緒隊列里還有這個事件的節點,再次獲取狀態,對!還是可讀的,所以還是不從就緒隊列里刪除,然后返回這個這個事件;對ET模式來說,就緒隊列里沒有這個事件的節點了,所以也就不會再對它進行通知了。那LT模式中的這個事件節點什么時候被刪除呢,假設第一次epoll_wait的時候,我們把管道里的內容全部讀完了,下次epoll_wait遍歷到這個節點然后重新獲取它的狀態的時候,它已經不再就緒了,因為管道空了,這個時候LT模式就不會再把這個節點重新添加到就緒隊列里了。

    Q:LT模式和ET模式各自的應用場所

    A:LT模式比較慢,但是比較安全,也就是如果真的是就緒的話它會再次通知你;而ET模式比較快,但是有可能造成事件的丟失,這就可能讓程序永遠阻塞。LT為了擔責,降低了效率,而ET為了效率將責任推給了用戶

  23. 最后的一分鍾

    Q:好了,面試就到這里了,你這兩天還在**嗎

    A:嗯還在,接下來會有什么安排嗎

    Q:我馬上給你安排一下復面,你應該很快就能收到消息

    A:嗯,好的,謝謝

    A:(從地上把包拿起放在腿上准備起身)評價一下我吧

    Q:很不錯

    A:這么簡單的嗎

    Q:嗯,很不錯...

    A:好吧...

總結(感想):第一場面試也是第一次面試,6歲的我就不能為面試慌一次?收到面試通知叫我前往面試官房間的時候特別緊張,在電梯里大呼了好幾口氣。剛開始不在狀態,后來馬上調整了過來,總體感覺發揮地不錯,問題幾乎能夠答得上來。面試官人也比較好,好幾次提醒了我,也和面試官談笑風生。面試題目大多來源於簡歷的個人技能,來源於項目很少。

二面(總監面)

過程:遞交簡歷 -> 開始面試 -> 結束

耗時:about 20 min

開始面試:

  1. 開始的一分鍾

    Q:介紹一下你在學校期間都學過哪些東西

    A:在學校期間幾乎所有東西都是自學...(然后介紹了大一上學期至大三下學期都學過哪些東西做過哪些東西對什么感興趣)

  2. 從簡歷上寫的項目中學到了什么

  3. STL allocator

    Q:介紹一下allocator

    A:...(從SGI STL源碼入手,把第一二級分配器介紹了一遍,着重介紹了內存池的實現)

  4. iterator 與 container 之間的耦合關系

    Q:介紹一下迭代器與容器之間的耦合關系

    A:在SGI STL中只有容器對迭代器的依賴關系,而迭代器並沒有對容器的耦合關系。所以,比如說vector擴容之后,迭代器會失效,解引用這樣的迭代器可能會造成非法訪問。但是以前用VisualStudio使用它的C++的STL庫CRT的時候,如果容器進行了擴容,然后解引用它們已失效的迭代器的時候,會引發異常。所以我猜想它們的實現里,一定是將迭代器與容器進行了關聯,每次對迭代器進行操作時候,都會根據容器檢驗迭代器的有效性,如果無效就拋出異常。

  5. Type traits的作用

    Q:類型萃取有什么作用

    A:...(我從STL設計里舉了好幾個例子來說明它的作用,但是好像說得不是很明白)

  6. 二叉搜索樹與哈希表

    Q:...(舉了幾個應用的例子,具體內容印象很模糊)

  7. 數據庫索引

    Q:數據庫索引的作用

    A:加速訪問

    Q:索引使用什么數據結構實現的

    A:...(我聽成了鍵是用什么實現的...然后就語塞)

    Q:是用hash表實現的嗎

    A:...(我好像回答的是???這個問題在關於hash表的問題之后,腦子有點懵)

  8. 數據庫事務

    Q:數據庫事務介紹一下

    A:...(數據庫基礎不是很好,只是簡單地介紹了這個操作的原子性,然后他又問我事務的實現是怎樣的,我只是講了一下個人的猜測...)

  9. 寫一個簡單的FTP服務器

    Q:我現在想要寫一個簡單的web服務器,響應用戶相應的數據,該怎么寫

    A:FTP服務器可以嗎

    Q:FTP服務器就FTP服務器吧...

    A:...(手寫偽代碼)

    Q:不用一行一行寫出來

    A:...(停下筆)首先創建一個服務器socket,然后bind地址,listen監聽,然后把socket加入多路轉接監聽鏈表。當有連接到達的時候,我們對socket調用accept,返回一個已連接套接字描述符,然后根據用戶傳輸過來的文件名去查找文件,讀取文件內容並回送給用戶(被打斷)

    Q:讀取文件的時候服務器socket怎么辦呢

    A:accept之后創建一個線程,如果使用線程池的話就從池中取一個空閑線程,然后把已連接文件描述符傳給這個線程,然后讓線程去處理這個用戶請求

    Q:一個線程處理一個用戶請求嗎

    A:對

  10. 設計網頁訪問cache數據結構

    Q:假設我想要緩存web服務器的訪問記錄,該如何實現這個數據結構

    A:用隊列吧,根據last visited排序,先進先出

    Q:如果你用隊列的話,你怎么確定cache是否命中呢

    A:emmm...你根據什么判斷是否命中

    Q:鍵

    A:那我還是用隊列,每一個元素包含鍵值兩部分,值的話呢就是訪問的記錄。然后我再用一個紅黑樹保存鍵值,這個值呢是指向隊列元素的指針

    A:其實用hash表更好一點,這樣更快,但是我一般都比較喜歡用紅黑樹...

  11. 最后的一分鍾

    Q:好了,就面到這里

    A:...(我都不敢相信只面這么短的時間,當時真的很虛很虛很虛)

    A:評價一下我吧

    Q:啊?(面試官全程無表情很高冷,可能被我這個問題驚呆了...)

    A:評價一下我

    Q:本科有這個基礎已經夠了,但是還是有一些不足

    A:數據庫和網絡嗎

    Q:你的數據庫基礎不是很好

    A:好的,謝謝,接下來還會有什么安排嗎

    Q:你回去等通知吧,我盡快讓HR聯系你,明天應該就行,最遲也就這一兩天

總結(感想):等叫號就超出預期時間50多分鍾,被叫號以后來到面試官房間,那時還有一個女生在面沒有出來。當時我以為是兩個人面我,然后我敲門,他讓我等一下。在門外聽見他們一直在討論數據結構與算法的問題...當時很慌,雖然不是很怕,但是在這種讓人緊張的環境下迅速把算法題做出來還是有些擔心。下午整體感覺不是很難,但是氛圍不是很好,因為面試官散發出一種吊炸天的氣質讓我很慫,而且我每說一句話他就嗯一大聲(有時候讓我特別尬),而上午那場是偶爾ok一下...以為二面會手撕很多算法,結果並沒有,虛驚一場。最后他說就面到這里的時候真的很有被嚇到,因為時間真的太短太短了吧...心想不會就這么涼了吧。然后主動問他要的評價也說我渣,以及“你回去等通知吧”,種種都讓我很慫。面試狀態當晚0點還是沒有更新,直到凌晨三點起床才發現狀態變成了HR面...面試題目全部來源於簡歷的個人技能以及項目經歷。

三面(HR面)

17號凌晨3點起床寫下的一二面面經,中午12點還在賴床然后接到HR電話通知14點前往酒店參加面試。那天心情狀態都不好還很困,下午hr面試的時候,hr小姐姐問什么就順口回答什么,沒有任何經過大腦思考,然后從話語出暴露出很多破綻,甚至還表現出了一些不存在的陰暗面和缺點。問的內容大致是學習方法、社交、未來規划、學歷、為什么不考研、為什么來微信事業群(志願填的是WXG、深圳-不服從調劑)...其實hr也會問項目的...而且她會仔細檢查簡歷比如說有沒有錯別字、項目時間科不科學等等等等...看別人的hr都有問戶籍啊有沒有女朋友之類的,可是為什么不問問我有沒有女朋友???(其實我早就心知肚明只是不願說透,她看我本人這么帥怎么可能會沒有女朋友嘛(害羞...)...其實我真的沒有女朋友啊...)

總結(感想):遭遇hr壓力面,以為自己鐵定會掛,並且面試狀態持續兩天都處在“hr面試中”,后來我主動問hr什么時候狀態才可能會更新,跟她說自己可能要涼涼,然后她反問我為什么覺得自己會掛,然后讓我去看狀態...以為最新狀態會是“不適合該崗位”的,看了之后是“已完成所有面試”,真是巨開心!


4月24日更新

4月23日上午10點半,收到offer call,下午5點半收到錄用函...


打個小廣告,推薦關注大牛(很多人應該認識...那個奧特曼...):
他的牛客:https://www.nowcoder.com/profile/517862
他的知乎:https://www.zhihu.com/people/UltramanEven/activities
也可以來找我一起學習(wan):
知乎、簡書同步ID:叫小丁不叫小丁丁

原文鏈接:https://www.jianshu.com/p/a5245ab978b3


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM