可可簡歷網

位置:首頁 > 面試 > 面試經驗

京東的面經分享


面試情況

此戰終結於技術面最後一面,值得深思。由於內推簡歷沒有直接通過篩選,參加了筆試才並有幸參加了面試,但是一面電話面結束後,面試官說如果有二面希望能現場面!

1 一面(電話面25分鐘)簡述一下專案

一面提專案,一般說明專案背景,自己做了什麼就好了,不會深問,但是能準備著更好

專案中遇到過什麼問題,怎麼解決

這個問題,凡是涉及專案基本上都跑不了,前面說過需要準備幾個面試官百分之80會問的關於專案的題。

都學過什麼課程,計算機方向是軟體工程嗎

計算機網路,資料結構,操縱系統,編譯原理,人工智慧,大資料等隨便你選幾個,保證自己能說出個123

C++中的類的大小計算

C++中類的成員函式,靜態成員是不佔類的大小的。類的大小等於基類的大小+子類個non-static成員變數的大小再+非虛基類大小,如果有多型性還要考慮vptr(可能不止一個)大小,這裡成員變數是會被位元組對齊的。

介紹一下http與https及區別

HTTPS和HTTP的區別

超文字傳輸協議HTTP協議被用於在Web瀏覽器和網站伺服器之間傳遞資訊。HTTP協議以明文方式傳送內容,不提供任何方式的資料加密,如果攻擊者截取了Web瀏覽器和網站伺服器之間的傳輸報文,就可以直接讀懂其中的資訊,因此HTTP協議不適合傳輸一些敏感資訊,比如信用卡號、密碼等。(此處可以使用wireshark工具模擬模擬,另外如果學習協議也可以考慮python的scapy/dpkt庫)

為了解決HTTP協議的這一缺陷,需要使用另一種協議:安全套接字層超文字傳輸協議HTTPS。為了資料傳輸的安全,HTTPS在HTTP的基礎上加入了SSL協議,SSL依靠證書來驗證伺服器的身份,併為瀏覽器和伺服器之間的通訊加密。

HTTPS和HTTP的區別主要為以下四點:

一、https協議需要到ca申請證書,一般免費證書很少,需要交費。

二、http是超文字傳輸協議,資訊是明文傳輸,https則是具有安全性的ssl加密傳輸協議(當然不是絕對安全,也可以通過特徵抽取,過濾,篩選,模型訓練進行搞事情!)。

三、http和https使用的是完全不同的連線方式,用的埠也不一樣,前者是80,後者是443。

四、http的連線很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網路協議,比http協議安全。

列印int時不小心用了%s會出現什麼問題段錯誤
 int i = 10;    
 char *s = "12"; 
 printf("%dn", s); // 資料不對
 printf("%sn", i); // 段錯誤
連結串列成環(快慢指標,提供思路即可,《劍指offer》)
京東的面經分享

[c++版本]


京東的面經分享 第2張

[python]版本


京東的面經分享 第3張


邏輯題

1000瓶無色無味的藥水,其中有一瓶毒藥,10只小白鼠拿過來做實驗。喝了無毒的藥水第二天沒事兒,喝了有毒的藥水後第二天會死亡。如何在一天之內(第二天)找出這瓶有毒的藥水?

思路就是用二進位制,2^10=1024,也就是10只小白鼠最多能驗出1024瓶藥水,哪個有毒。小白鼠編號,1-10。瓶子也編號,1-1000,然後把瓶子的編號轉變為二進位制數。如果第幾位是1,就把這瓶水給第幾個小白鼠喝。最後大概每個小白鼠喝500瓶藥水的混合液。如果還不懂,下面列幾個數字解釋一下。

瓶子編號 二進位制數 第幾個小白鼠喝

1 0000000001 1

2 0000000010 2

3 0000000011 1,2

4 0000000100 3

5 0000000101 1,3

大概就是這意思,再反過來,假如1號和3號小白鼠死了,死的小白鼠用1表示,再寫成2進位制數:0000000101,轉化為十進位制數是5,從上面列出來的也可以看出1,3都喝了5號瓶的水,所以就是第五瓶水有毒。

解決方案
1)我們將1000瓶液體編號1~1000,然後將編號轉化為10位二進位制,如1號就是0000000001;


2)將十隻小白鼠編號1~10;


3)將液體的二進位制編號上為1的位數給對應的小白鼠喝,如液體編號為 1111100000,那就是1~5號小白鼠不喝這瓶液體,6~10號小白鼠喝這瓶液體;


4)一星期後觀察小白鼠的死亡情況,如果1~5號小白鼠死亡,6~10號小白鼠存活,那麼有毒的那瓶液體對應的二進位制編碼為 0000011111;


5)將第四步得到的二進位制編碼轉化為十進位制,這裡是31號,因此我們可以推斷出編號為31的液體是被汙染的。

cookie 和session 的區別:

cookie和session的共同之處在於:cookie和session都是用來跟蹤瀏覽器使用者身份的會話方式。

cookie 和session 的區別:

1、cookie資料存放在客戶的瀏覽器上,session資料放在伺服器上。

2、cookie不是很安全,別人可以分析存放在本地的COOKIE並進行COOKIE欺騙,考慮到安全應當使用session。

3、session會在一定時間內儲存在伺服器上,超過時間會銷燬這個SESSION。當訪問增多,會比較佔用你伺服器的效能考慮到減輕伺服器效能方面,應當使用COOKIE。

4、單個cookie儲存的資料不能超過4K,很多瀏覽器都限制一個站點最多儲存20個cookie。

5、所以個人建議:將登陸資訊等重要資訊存放為SESSION,其他資訊如果需要保留,可以放在COOKIE中

還有什麼可以問我的嗎

這個問題一般來說會有二面,只要不問一些敏感話題就行了。

第二天早上收到二面通知,但是說需要現場面。思考了半天,決定還是去現場面試,雖然需要差不多單程900的車費,萬一現場面試更簡單呢是吧。當然我也知道,我不去一定會後悔,索性還是去嘗試未嘗不是一件好事,畢竟正好還有小米和滴滴,bigo的現場面試。從南方到北方,郵箱通知上面是九點到西土城的泰富酒店簽到,下火車時間差不多為六點多,所以到達那裡的時候差不多七點,我是第一個到那裡並簽到的,然後就在那裡看自己準備的演算法題,其實昨天晚上在火車上也複習了很久,因為我會盡全力的去完成這次任務,以至今也沒後悔之言。北京的天空依然那麼的純藍!

京東的面經分享 第4張

[北京西站]

2 二面(現場面)

我們簽到以後,面試官可以看見簽到時間,是一哥很溫柔的小哥,讓我把行李放了坐下,別緊張,先自我介紹,然後他說,你這麼遠過來其實沒必要的,可以申請遠端的,不然太折騰了,今天我們就簡單問問。

自我介紹

自我介紹完了以後

面試官:你覺得你的一面感覺如何

我:我說一面面試官很好(其實我從之前的溝通中已經感覺一面二面是同一個面試官了),不太會的都會引導我,然後回頭查了相關的資料。面試官還是比較滿意的。注意:覆盤很重要,一般都有面試記錄的。

我看你寫了三個專案,說一個熟悉一些的,背景,你做了啥,有什麼難點

面試官:我們看幾個簡單題

建構函式為什麼不能是虛擬函式

虛擬函式的呼叫需要虛擬函式表指標,而該指標存放在物件的內容空間中;若建構函式宣告為虛擬函式,那麼由於物件還未建立,還沒有記憶體空間,更沒有虛擬函式表地址用來呼叫虛擬函式。

Makefile、GDB應該都用過吧

可以參考陳皓很多年前寫的一個專欄,如果沒找到電子版可以私我!

原子變數和volatile區別(C++11)

Volatile變數可以確保先行關係,即寫操作會發生在後續的讀操作之前, 但它並不能保證原子性。例如用volatile修飾count變數那麼 count++ 操作就不是原子性的。而AtomicInteger類提供的atomic方法可以讓這種操作具有原子性如getAndIncrement()方法會原子性的進行增量操作把當前值加一,其它資料型別和引用變數也可以進行相似操作。

智慧指標介紹(C++11)

_ptr主要是用來解決資源自動釋放的問題;auto_ptr支援賦值和複製,將指標的所有權轉移,但是如果轉移後再訪問原來得指標,行為不確定,程式可能會在執行時出錯。

ue_ptr與auto_ptr一樣,也是建立所有權機制,但是不支援複製和賦值,所以將一個unique_ptr物件賦值給另一個時,程式編譯出錯;但如果將臨時的unique_ptr賦值或複製給另一個物件時,沒有問題。unique_ptr比auto_ptr更安全。

ed_ptr和unique_ptr都只能一個智慧指標引用物件,而shared_ptr則是可以多個智慧指標同時擁有一個物件。shared_ptr實現方式就是使用引用計數。引用計數的原理是,多個智慧指標同時引用一個物件,每當引用一次,引用計數加一,每當智慧指標銷燬了,引用計數就減一,當引用計數減少到0的時候就釋放引用的物件。這種引用計數的增減發生在智慧指標的建構函式,複製建構函式,賦值操作符,解構函式中。

這種方式使得多個智慧指標同時對所引用的物件有擁有權,同時在引用計數減到0之後也會自動釋放記憶體,也實現了auto_ptr和unique_ptr的資源釋放的功能。

_ptr,shared_ptr是一種強引用的關係,智慧指標直接引用物件。那麼這個會程式碼一個隱含的問題,就是迴圈引用,從而造成記憶體洩漏,首先來看一個迴圈引用的例子。

class Parent
{
public:
  shared_ptr<Child> child;
};
class Child
{
public:
  shared_ptr<Parent> parent;
};
void Function()
{
shared_ptr<Parent> pA(new Parent);
shared_ptr<Child> pB(new Child);
pA->child = pB;
pB->parent = pA;
}
//第一條語句使得pA引用了Parent一個指標,Parent引用計數為1
//第二條語句使得pB引用了Child一個指標,Child引用計數為1
//第三條語句,呼叫了shared_ptr<Child>類的賦值操作符,使得Child引用計數變為2
//第四條語句,呼叫了shared_ptr<Parent>類的賦值操作符,使得Parent引用計數變為
//函式返回之前呼叫了shared_ptr<Parent>和shared_ptr<Child>類的析夠函式,使得Child引用計數變為1,Parent引用計數變為1

咱們看,函式執行完之後new出來的Parent和Child並沒有釋放,所以出現了記憶體洩漏(說出這幾個字之前,自己應該至少知道哪些工具可以檢測記憶體洩漏等相關問題)。

出現洩漏的原因就是pA和pB相互引用了,導致兩者所引用物件的引用計數不能減少到0,造成洩漏。

如果把第三條語句或者第四條語句任意刪除一個,就不會有洩漏了。這就是強引用所帶來的問題。weak_ptr從字面意思上可以看出是一個弱指標,不是說明這個指標的能力比較弱,而是說他對他所引用的物件的所有權比較弱,說得更直接一點兒就是他並不擁有所引用物件的所有權,而且他還不能直接使用他所引用的物件。

在stl中,weak_ptr是和shared_ptr配合使用的,在實現shared_ptr的時候也就考慮了weak_ptr的因素。weak_ptr是shared_ptr的觀察者,它不會干擾shared_ptr所共享物件的所有權,當一個weak_ptr所觀察的shared_ptr要釋放它的資源時,它會把相關的weak_ptr的指標設定為空,防止weak_ptr持有懸空的指標。注意:weak_ptr並不擁有資源的所有權,所以不能直接使用資源。可以從一個weak_ptr構造一個shared_ptr以取得共享資源的所有權。

weak_ptr是為配合shared_ptr而引入的一種智慧指標,它更像是shared_ptr的一個助手,而不是智慧指標,因為它不具有普通指標的行為,沒有過載operator*和operator->,它的最大作用在於協助shared_ptr,像旁觀者那樣觀測資源的使用情況。

weak_ptr被設計為與shared_ptr共同工作,可以從一個shared_ptr或者另一個weak_ptr物件構造,獲得資源的觀測權。但weak_ptr沒有共享資源,它的構造不會引起指標引用計數的增加。同樣,在weak_ptr析構時也不會導致引用計數的減少,它只是一個靜靜地觀察者。

使用weak_ptr的成員函式use_count()可以觀測資源的引用計數,另一個成員函式expired()的功能等價於use_count() == 0,但更快,表示觀測的資源(也就是shared_ptr管理的資源)已經不復存在了。

weak_ptr 沒有過載operator*和->,這是特意的,因為它不共享指標,不能操作資源,這是它弱的原因。但它可以使用一個非常重要的成員函式lock()從被觀測的shared_ptr獲得一個可用的shared_ptr物件,從而操作資源。當expired() == true的時候,lock()函式將返回一個儲存空指標的shared_ptr。

智慧指標內部實現(C++11)

智慧指標類將一個計數器與類指向的物件相關聯,引用計數跟蹤該類有多少個物件共享同一指標。每次建立類的新物件時,初始化指標並將引用計數置為1;


當物件作為另一物件的副本而建立時,拷貝建構函式拷貝指標並增加與之相應的引用計數;對一個物件進行賦值時,賦值操作符減少左運算元所指物件的引用計數(如果引用計數為減至0,則刪除物件),並增加右運算元所指物件的引用計數;

呼叫解構函式時,建構函式減少引用計數(如果引用計數減至0,則刪除基礎物件)。智慧指標就是模擬指標動作的類。所有的智慧指標都會過載 -> 和 * 操作符。智慧指標還有許多其他功能,比較有用的是自動銷燬。這主要是利用棧物件的有限作用域以及臨時物件(有限作用域實現)解構函式釋放記憶體。

DPDK內部實現(這個是因為簡歷上有寫,關於一個高效能資料包處理庫)

Winpcap:它的一個流程是npf網路組包過濾器首先負責從網路中採集資料包,完成資料的過濾拷貝到核心快取區,然後呼叫相應的動態庫檔案將資料傳遞到應用層緩衝區,最後應用程式處理。具體工作原理

(1)網絡卡接受資料包到達資訊,然後產生硬體中斷,通知cpu排程處理,中斷服務程式判斷資料包的有效性,分配一個緩衝。

(2)BPF模組根據使用者的規則過濾資料包,並把資料包插入到核心的網絡卡驅動緩衝佇列中。

(3)使用者程式通過系統呼叫用來讀取核心緩衝區的資料包 完成資料採集。

優化方案

(1)使用雙緩衝減少執行緒鎖。

(2)多執行緒。

(3)將原始的資料包還原成流儲存 減少對資料包的儲存,在核心層提供了通用socket環形緩衝,不進入核心協議棧,最後在應用層通過socket連結同時使用mmap技術直接訪問socket環狀緩衝區

libevent結構、內部實現(回撥+同步)、多執行緒實現

首先I/O複用經過封裝;

統一事件源(I/O事件,訊號事件,定時事件);

事件處理提前註冊(回撥函式)。

Libevent是執行緒不安全的,但是libevent提供了鎖機制,而且在實現框架上儘量避免使用鎖,像memcache多執行緒使用libevent,他的實現現架是主執行緒監聽到讀寫事件分發任務(使用CQ佇列),每個工作執行緒對應一個CQ佇列。

上面提到的兩個網路庫可以去看看,資料很全的。

epoll內部實現

紅黑樹 就緒事件雙向連結串列;每當就緒事件到來時,通過實現註冊好的回撥函式將就緒事件加入到就緒事件佇列中,epoll_wait返回時只需要遍歷就緒事件雙向連結串列。

timewait作用

客戶端收到服務的釋放連線的請求後,不是立馬進入CLOSE狀態,而是還要再等待2MSL。理由是:

確保最後一個確認報文能夠到達。如果沒能到達,服務端就會會重發FIN請求釋放連線。等待一段時間沒有收到重發就說明服務的已經CLOSE了。如果有重發,則客戶端再發送一次LAST ack訊號

等待一段時間是為了讓本連線持續時間內所產生的所有報文都從網路中消失,使得下一個新的連線不會出現舊的連線請求報文

程式設計題1 手撕快排
京東的面經分享 第5張

程式設計題2 二分查詢變種

二分查詢以及變種的總結


3 總結

這次面試難度還行,甚至沒有涉及到分散式,微服務,負載均衡等問題。最終雖然敗北,但是學會了一下幾點:

公司招你去是幹活了,不會因為你怎麼怎麼的而降低對你的要求標準。在工具上寫程式碼和手撕程式碼完全不一樣。珍惜每一次面試機會並學會覆盤。對於應屆生主要考察的還是計算機基礎知識的掌握,專案要求沒有那麼高,是自己做的專案就使勁摳細節,做測試。只有這樣,才知道會遇到什麼問題,遇到什麼難點,如何解決的。從而可以侃侃而談了。

標籤:面經 京東