C++面試八股文:什麼是空指標/野指標/懸垂指標?

2023-07-01 06:00:30

某日二師兄參加XXX科技公司的C++工程師開發崗位第30面:

面試官:什麼是空指標?

二師兄:一般我們將等於0/NULL/nullptr的指標稱為空指標。空指標不能被解除參照,但是可以對空指標取地址。

int* p = nullptr;	//空指標
*p = 42;	//空指標不可以解除參照
int** pp = &p	//空指標可以取地址

面試官:你知道0/NULL/nullptr三者之間的區別嗎?

二師兄:雖然三者都能定義空指標,但三者型別不同。

二師兄:0int型別,NULL在g++下是一個宏定義,而nullptr是有型別的;

#define NULL ((void *)0)

typedef decltype(nullptr) nullptr_t;

sizeof(0);// 4
sizeof(NULL);//8
sizeof(nullptr);//8

二師兄:在函數過載時,會根據實參的型別選擇過載函數:

#include <iostream>
void fun(int) {std::cout << "int" << std::endl;}
void fun(int*) {std::cout << "int*" << std::endl;}
void fun(nullptr_t) {std::cout << "nullptr_t" << std::endl;}
int main(int argc, char const *argv[])
{
    fun(0);	//編譯通過,匹配fun(int)
    fun(NULL);	//編譯失敗,可以匹配 fun(int) fun(int*) fun(nullptr_t)
    fun(nullptr);	//編譯成功,匹配fun(nullptr_t)
    return 0;
}

二師兄:在C++11之後,建議使用nullptr定義空指標,因為它時有型別的,編譯器能夠對它進行型別檢查。

面試官:什麼是野指標?

二師兄:野指標突出一個野字,這個野就是狀態未知的。它可能指向一塊未知的區域:

int* p;		//野指標,指標未初始化
*p = 42;	//對野指標解除參照,未定義的操作

面試官:什麼是垂懸指標?

二師兄:垂懸指標是指指標指向的內容已被釋放,指標指向的物件的生命週期已結束。

int* p = new int(42);
delete p;
*p = 1024;	//垂懸指標,指標指向的物件已被釋放

int* p = nullptr;
{
    int i = 42;
    p = &i;
}
*p = 1024; //垂懸指標,指向的物件的生命週期已結束

面試官:如何解決空指標、野指標、垂懸指標帶來的問題?

二師兄:主要可以從有以下幾點入手:

1.在解除參照指標之前,要判斷指標是否為空。(解決空指標解除參照問題)

2.對於定義的指標,一定要進行初始化(=nullptr)。(解決野指標問題)

3.對於釋放過內容的指標,立即將指標置為nullptr。(解決垂懸指標、指標二次釋放問題)

4.要注意長生命週期的指標不能指向短生命週期的物件。(解決垂懸指標問題)

5.C++11之後使用智慧指標。

面試官:好的。那你知道什麼是記憶體漏失(memory leak)嗎?

二師兄:記憶體漏失是指分配的記憶體空間沒有被正確釋放的情況。常見的情況有malloc沒有freenew沒有deletenew[]delete混用。

面試官:如何防範記憶體漏失問題?

二師兄:最簡單的辦法是使用資源獲取即初始化(RAII)技術將資源放在類中管理,在類構造時獲取資源(malloc/new),在類的解構函式中釋放資源(free/delete),使用C++的構造和解構機制保證資源的正確申請和釋放。

二師兄:我們常用的std::shared_ptrstd::unique_ptrstd::lock_guard就是採用這種技術管理資源。

面試官:最後一個問題,如何查詢程式中是否出現了記憶體漏失?

二師兄:只要有兩種方法:

1.自己動手:把所有使用malloc/free的地方改成new/delete,過載全域性的newdelete,並加入申請和釋放記憶體容量的統計邏輯。

2.採用工具:可以使用諸如Valgrind(在Linux上)或Dr. Memory(在Windows上)等記憶體偵錯工具來檢測記憶體漏失。這些工具可以在執行程式時檢測記憶體漏失,並提供詳細的報告和偵錯資訊。

面試官:好的。今天的面試結束,請等訊息。

今天的面試到這裡就結束了,祝大家週末愉快~

關注我,帶你21天「精通」C++!(狗頭)