日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

二十万字C/C++、嵌入式软开面试题全集宝典五

發(fā)布時(shí)間:2025/3/15 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二十万字C/C++、嵌入式软开面试题全集宝典五 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

81、 vector越界訪問(wèn)下標(biāo),map越界訪問(wèn)下標(biāo)?vector刪除元素時(shí)會(huì)不會(huì)釋放空間?

82、 map[]與find的區(qū)別?

83、 STL中l(wèi)ist與queue之間的區(qū)別

84、 STL中的allocator,deallocator

85、 STL中hash_map擴(kuò)容發(fā)生什么?

86、 map如何創(chuàng)建?

87、 vector的增加刪除都是怎么做的?為什么是1.5倍?

88、 C++ sort排序算法底層

89、 函數(shù)指針?

90、 C與C++的聯(lián)系與區(qū)別

91、 C++中NULL和nullptr的區(qū)別

92、 C/C++內(nèi)存分配

93、 c/c++的內(nèi)存分配模型,詳細(xì)說(shuō)一下棧、堆、靜態(tài)存儲(chǔ)區(qū)?

94、 野指針是什么?如何檢測(cè)內(nèi)存泄漏?

95、 懸空指針和野指針有什么區(qū)別?

96、 內(nèi)存泄漏

97、 內(nèi)存溢出定位

98、 什么是內(nèi)存對(duì)齊

99、 為什么內(nèi)存對(duì)齊

100、 內(nèi)存對(duì)齊規(guī)則


?

81、 vector越界訪問(wèn)下標(biāo),map越界訪問(wèn)下標(biāo)?vector刪除元素時(shí)會(huì)不會(huì)釋放空間?

1.通過(guò)下標(biāo)訪問(wèn)vector中的元素時(shí)不會(huì)做邊界檢查,即便下標(biāo)越界。也就是說(shuō),下標(biāo)與first迭代器相加的結(jié)果超過(guò)了finish迭代器的位置,程序也不會(huì)報(bào)錯(cuò),而是返回這個(gè)地址中存儲(chǔ)的值。如果想在訪問(wèn)vector中的元素時(shí)首先進(jìn)行邊界檢查,可以使用vector中的at函數(shù)。通過(guò)使用at函數(shù)不但可以通過(guò)下標(biāo)訪問(wèn)vector中的元素,而且在at函數(shù)內(nèi)部會(huì)對(duì)下標(biāo)進(jìn)行邊界檢查。
2.map的下標(biāo)運(yùn)算符[]的作用是:將key作為下標(biāo)去執(zhí)行查找,并返回相應(yīng)的值;如果不存在這個(gè)key,就將一個(gè)具有該key和value的某人值插入這個(gè)map。
3.erase()函數(shù),只能刪除內(nèi)容,不能改變?nèi)萘看笮? erase成員函數(shù),它刪除了itVect迭代器指向的元素,并且返回要被刪除的itVect之后的迭代器,迭代器相當(dāng)于一個(gè)智能指針;clear()函數(shù),只能清空內(nèi)容,不能改變?nèi)萘看笮?如果要想在刪除內(nèi)容的同時(shí)釋放內(nèi)存,那么你可以選擇deque容器。

82、 map[]與find的區(qū)別?

1.map的下標(biāo)運(yùn)算符[]的作用是:將關(guān)鍵碼作為下標(biāo)去執(zhí)行查找,并返回對(duì)應(yīng)的值;如果不存在這個(gè)關(guān)鍵碼,就將一個(gè)具有該關(guān)鍵碼和值類(lèi)型的默認(rèn)值的項(xiàng)插入這個(gè)map。
2.map的find函數(shù):用關(guān)鍵碼執(zhí)行查找,找到了返回該位置的迭代器;如果不存在這個(gè)關(guān)鍵碼,就返回尾迭代器。

83、 STL中l(wèi)ist與queue之間的區(qū)別

1.list不再能夠像vector一樣以普通指針作為迭代器,因?yàn)槠涔?jié)點(diǎn)不保證在存儲(chǔ)空間中連續(xù)存在;
2.list插入操作和結(jié)合才做都不會(huì)造成原有的list迭代器失效;
3.list不僅是一個(gè)雙向鏈表,而且還是一個(gè)環(huán)狀雙向鏈表,所以它只需要一個(gè)指針;
4.list不像vector那樣有可能在空間不足時(shí)做重新配置、數(shù)據(jù)移動(dòng)的操作,所以插入前的所有迭代器在插入操作之后都仍然有效;
5.deque是一種雙向開(kāi)口的連續(xù)線性空間,所謂雙向開(kāi)口,意思是可以在頭尾兩端分別做元素的插入和刪除操作;可以在頭尾兩端分別做元素的插入和刪除操作;
6.deque和vector最大的差異,一在于deque允許常數(shù)時(shí)間內(nèi)對(duì)起頭端進(jìn)行元素的插入或移除操作,二在于deque沒(méi)有所謂容量概念,因?yàn)樗莿?dòng)態(tài)地以分段連續(xù)空間組合而成,隨時(shí)可以增加一段新的空間并鏈接起來(lái),deque沒(méi)有所謂的空間保留功能。

84、 STL中的allocator,deallocator

1.第一級(jí)配置器直接使用malloc()、free()和relloc(),第二級(jí)配置器視情況采用不同的策略:當(dāng)配置區(qū)塊超過(guò)128bytes時(shí),視之為足夠大,便調(diào)用第一級(jí)配置器;當(dāng)配置器區(qū)塊小于128bytes時(shí),為了降低額外負(fù)擔(dān),使用復(fù)雜的內(nèi)存池整理方式,而不再用一級(jí)配置器;
2.第二級(jí)配置器主動(dòng)將任何小額區(qū)塊的內(nèi)存需求量上調(diào)至8的倍數(shù),并維護(hù)16個(gè)free-list,各自管理大小為8~128bytes的小額區(qū)塊;
3.空間配置函數(shù)allocate(),首先判斷區(qū)塊大小,大于128就直接調(diào)用第一級(jí)配置器,小于128時(shí)就檢查對(duì)應(yīng)的free-list。如果free-list之內(nèi)有可用區(qū)塊,就直接拿來(lái)用,如果沒(méi)有可用區(qū)塊,就將區(qū)塊大小調(diào)整至8的倍數(shù),然后調(diào)用refill(),為free-list重新分配空間;
4.空間釋放函數(shù)deallocate(),該函數(shù)首先判斷區(qū)塊大小,大于128bytes時(shí),直接調(diào)用一級(jí)配置器,小于128bytes就找到對(duì)應(yīng)的free-list然后釋放內(nèi)存。

85、 STL中hash_map擴(kuò)容發(fā)生什么?

1.hash table表格內(nèi)的元素稱(chēng)為桶(bucket),而由桶所鏈接的元素稱(chēng)為節(jié)點(diǎn)(node),其中存入桶元素的容器為stl本身很重要的一種序列式容器——vector容器。之所以選擇vector為存放桶元素的基礎(chǔ)容器,主要是因?yàn)関ector容器本身具有動(dòng)態(tài)擴(kuò)容能力,無(wú)需人工干預(yù)。
2.向前操作:首先嘗試從目前所指的節(jié)點(diǎn)出發(fā),前進(jìn)一個(gè)位置(節(jié)點(diǎn)),由于節(jié)點(diǎn)被安置于list內(nèi),所以利用節(jié)點(diǎn)的next指針即可輕易完成前進(jìn)操作,如果目前正巧是list的尾端,就跳至下一個(gè)bucket身上,那正是指向下一個(gè)list的頭部節(jié)點(diǎn)。

86、 map如何創(chuàng)建?

1.vector 底層數(shù)據(jù)結(jié)構(gòu)為數(shù)組 ,支持快速隨機(jī)訪問(wèn)
2.list底層數(shù)據(jù)結(jié)構(gòu)為雙向鏈表,支持快速增刪
3.deque底層數(shù)據(jù)結(jié)構(gòu)為一個(gè)中央控制器和多個(gè)緩沖區(qū),詳細(xì)見(jiàn)STL源碼剖析P146,支持首尾(中間不能)快速增刪,也支持隨機(jī)訪問(wèn)
deque是一個(gè)雙端隊(duì)列(double-ended queue),也是在堆中保存內(nèi)容的。它的保存形式如下:
[堆1] --> [堆2] -->[堆3] --> ...
每個(gè)堆保存好幾個(gè)元素,然后堆和堆之間有指針指向,看起來(lái)像是list和vector的結(jié)合品.
4.stack 底層一般用list或deque實(shí)現(xiàn),封閉頭部即可,不用vector的原因應(yīng)該是容量大小有限制,擴(kuò)容耗時(shí)
5.queue 底層一般用list或deque實(shí)現(xiàn),封閉頭部即可,不用vector的原因應(yīng)該是容量大小有限制,擴(kuò)容耗時(shí)(stack和queue其實(shí)是適配器,而不叫容器,因?yàn)槭菍?duì)容器的再封裝)
6.priority_queue 的底層數(shù)據(jù)結(jié)構(gòu)一般為vector為底層容器,堆heap為處理規(guī)則來(lái)管理底層容器實(shí)現(xiàn)
7.set 底層數(shù)據(jù)結(jié)構(gòu)為紅黑樹(shù),有序,不重復(fù)
8.multiset 底層數(shù)據(jù)結(jié)構(gòu)為紅黑樹(shù),有序,可重復(fù)
9.map底層數(shù)據(jù)結(jié)構(gòu)為紅黑樹(shù),有序,不重復(fù)
10.multimap 底層數(shù)據(jù)結(jié)構(gòu)為紅黑樹(shù),有序,可重復(fù)
11.hash_set 底層數(shù)據(jù)結(jié)構(gòu)為hash表,無(wú)序,不重復(fù)
12.hash_multiset 底層數(shù)據(jù)結(jié)構(gòu)為hash表,無(wú)序,可重復(fù)
13.hash_map 底層數(shù)據(jù)結(jié)構(gòu)為hash表,無(wú)序,不重復(fù)
14.hash_multimap 底層數(shù)據(jù)結(jié)構(gòu)為hash表,無(wú)序,可重復(fù)

87、 vector的增加刪除都是怎么做的?為什么是1.5倍?

1.新增元素:vector通過(guò)一個(gè)連續(xù)的數(shù)組存放元素,如果集合已滿,在新增數(shù)據(jù)的時(shí)候,就要分配一塊更大的內(nèi)存,將原來(lái)的數(shù)據(jù)復(fù)制過(guò)來(lái),釋放之前的內(nèi)存,在插入新增的元素;
2.對(duì)vector的任何操作,一旦引起空間重新配置,指向原vector的所有迭代器就都失效了;
3.初始時(shí)刻vector的capacity為0,塞入第一個(gè)元素后capacity增加為1;
4.不同的編譯器實(shí)現(xiàn)的擴(kuò)容方式不一樣,VS2015中以1.5倍擴(kuò)容,GCC以2倍擴(kuò)容。
對(duì)比可以發(fā)現(xiàn)采用采用成倍方式擴(kuò)容,可以保證常數(shù)的時(shí)間復(fù)雜度,而增加指定大小的容量只能達(dá)到O(n)的時(shí)間復(fù)雜度,因此,使用成倍的方式擴(kuò)容。
擴(kuò)容倍數(shù)
考慮可能產(chǎn)生的堆空間浪費(fèi),成倍增長(zhǎng)倍數(shù)不能太大,使用較為廣泛的擴(kuò)容方式有兩種,以2二倍的方式擴(kuò)容,或者以1.5倍的方式擴(kuò)容。
1.以2倍的方式擴(kuò)容,導(dǎo)致下一次申請(qǐng)的內(nèi)存必然大于之前分配內(nèi)存的總和,導(dǎo)致之前分配的內(nèi)存不能再被使用,所以最好倍增長(zhǎng)因子設(shè)置為(1,2)之間;
2.向量容器vector的成員函數(shù)pop_back()可以刪除最后一個(gè)元素;
3.而函數(shù)erase()可以刪除由一個(gè)iterator指出的元素,也可以刪除一個(gè)指定范圍的元素。
4.還可以采用通用算法remove()來(lái)刪除vector容器中的元素.
5.不同的是:采用remove一般情況下不會(huì)改變?nèi)萜鞯拇笮?#xff0c;而pop_back()與erase()等成員函數(shù)會(huì)改變?nèi)萜鞯拇笮 ?/p>

88、 C++ sort排序算法底層

sort作為一個(gè)內(nèi)置的排序方法,可以被vector等直接調(diào)用。
對(duì)于STL中的sort()算法:
1.當(dāng)數(shù)據(jù)量大時(shí),將會(huì)采用Quick Sort(快排),分段遞歸進(jìn)行排序。
2.一旦分段后的數(shù)據(jù)量小于某個(gè)閾值,為了避免快排的遞歸帶來(lái)過(guò)大的額外的開(kāi)銷(xiāo),sort()算法就自動(dòng)改為Insertion Sort(插入排序)。
3.如果遞歸的層次過(guò)深,還會(huì)改用Heap Sort(堆排序)。
簡(jiǎn)單來(lái)說(shuō),sort并非只是普通的快速排序,除了對(duì)普通的快排進(jìn)行優(yōu)化,它還結(jié)合了插入排序和堆排序。根據(jù)不同的數(shù)量級(jí)以及不同的情況,能夠自動(dòng)選擇合適的排序算法。

89、 函數(shù)指針?

1.什么是函數(shù)指針?
函數(shù)指針指向的是特殊的數(shù)據(jù)類(lèi)型,函數(shù)的類(lèi)型是由其返回的數(shù)據(jù)類(lèi)型和其參數(shù)列表共同決定的,而函數(shù)的名稱(chēng)則不是其類(lèi)型的一部分。
一個(gè)具體函數(shù)的名字,如果后面不跟調(diào)用符號(hào)(即括號(hào)),則該名字就是該函數(shù)的指針(注意:大部分情況下,可以這么認(rèn)為,但這種說(shuō)法并不很?chē)?yán)格)。
2.函數(shù)指針的聲明方法
int (*pf)(const int&, const int&); (1)
上面的pf就是一個(gè)函數(shù)指針,指向所有返回類(lèi)型為int,并帶有兩個(gè)const int&參數(shù)的函數(shù)。注意*pf兩邊的括號(hào)是必須的,否則上面的定義就變成了:
int*pf(const int&, const int&); (2)
而這聲明了一個(gè)函數(shù)pf,其返回類(lèi)型為int *, 帶有兩個(gè)const int&參數(shù)。
3.為什么有函數(shù)指針
○1函數(shù)與數(shù)據(jù)項(xiàng)相似,函數(shù)也有地址(函數(shù)名就是指針)。我們希望在同一個(gè)函數(shù)中通過(guò)使用相同的形參在不同的時(shí)間使用產(chǎn)生不同的效果。
○2一個(gè)函數(shù)名就是一個(gè)指針,它指向函數(shù)的代碼。一個(gè)函數(shù)地址是該函數(shù)的進(jìn)入點(diǎn),也就是調(diào)用函數(shù)的地址。函數(shù)的調(diào)用可以通過(guò)函數(shù)名,也可以通過(guò)指向函數(shù)的指針來(lái)調(diào)用。函數(shù)指針還允許將函數(shù)作為變?cè)獋鬟f給其他函數(shù);
○3兩種方法賦值:
指針名 = 函數(shù)名;指針名 = &函數(shù)名

90、 C與C++的聯(lián)系與區(qū)別

一、C++與C的聯(lián)系:
1、C++是在C語(yǔ)言的基礎(chǔ)上開(kāi)發(fā)的一種面向?qū)ο缶幊陶Z(yǔ)言,應(yīng)用廣泛。C++支持多種編程范式 --面向?qū)ο缶幊獭⒎盒途幊毯瓦^(guò)程化編程。 其編程領(lǐng)域眾廣,常用于系統(tǒng)開(kāi)發(fā),引擎開(kāi)發(fā)等應(yīng)用領(lǐng)域,是最受廣大程序員受用的最強(qiáng)大編程語(yǔ)言之一,支持類(lèi):類(lèi)、封裝、重載等特性!
2、C++在C的基礎(chǔ)上增添類(lèi),C是一個(gè)結(jié)構(gòu)化語(yǔ)言,它的重點(diǎn)在于算法和數(shù)據(jù)結(jié)構(gòu)。C程序的設(shè)計(jì)首要考慮的是如何通過(guò)一個(gè)過(guò)程,對(duì)輸入(或環(huán)境條件)進(jìn)行運(yùn)算處理得到輸出(或?qū)崿F(xiàn)過(guò)程(事務(wù))控制),而對(duì)于C++,首要考慮的是如何構(gòu)造一個(gè)對(duì)象模型,讓這個(gè)模型能夠契合與之對(duì)應(yīng)的問(wèn)題域,這樣就可以通過(guò)獲取對(duì)象的狀態(tài)信息得到輸出或?qū)崿F(xiàn)過(guò)程(事務(wù))控制。
二、C++與C的區(qū)別
1、C是面向過(guò)程的語(yǔ)言,而C++是面向?qū)ο蟮恼Z(yǔ)言,那么什么是面向?qū)ο?#xff1f;
面向?qū)ο?#xff1a;面向?qū)ο笫且环N對(duì)現(xiàn)實(shí)世界的理解和抽象的方法、思想,通過(guò)將需求要素轉(zhuǎn)化為對(duì)象進(jìn)行問(wèn)題處理的一種思想。
2、C和C++動(dòng)態(tài)管理內(nèi)存的方法不一樣,C是使用malloc、free函數(shù),而C++不僅有malloc/free,還有new/delete關(guān)鍵字。那malloc/free和new/delete差別?
malloc/free和new/delete差別:
①malloc/free是C和C++語(yǔ)言的標(biāo)準(zhǔn)庫(kù)函數(shù),需要頭文件包含,new/delete是C++的運(yùn)算符,關(guān)鍵字,需要編譯器支持。它們都可用于申請(qǐng)動(dòng)態(tài)內(nèi)存和釋放內(nèi)存。
②由于malloc/free是庫(kù)函數(shù)不是運(yùn)算符,不在編譯器范圍之內(nèi),不能夠把執(zhí)行構(gòu)造函數(shù)和析構(gòu)函數(shù)的任務(wù)強(qiáng)加入malloc/free。因此C++需要一個(gè)能完成動(dòng)態(tài)內(nèi)存分配和初始化工作的運(yùn)算符new,一個(gè)能完成清理與釋放內(nèi)存工作的運(yùn)算符delete。
③new可以認(rèn)為是malloc加構(gòu)造函數(shù)的執(zhí)行。new出來(lái)的指針是直接帶類(lèi)型信息的。而malloc返回的都是void指針。
④malloc是從堆上開(kāi)辟空間,而new是從自由存儲(chǔ)區(qū)開(kāi)辟(自由存儲(chǔ)區(qū)是從C++抽象出來(lái)的概念,不僅可以是堆,還可以是靜態(tài)存儲(chǔ)區(qū))。
⑤malloc對(duì)開(kāi)辟的空間大小有嚴(yán)格指定,而new只需要對(duì)象名。
⑥malloc開(kāi)辟的內(nèi)存如果太小,想要換一塊大一點(diǎn)的,可以調(diào)用relloc實(shí)現(xiàn),但是new沒(méi)有直觀的方法來(lái)改變。
3、C中的struct和C++的類(lèi),C++的類(lèi)是C中沒(méi)有的,C中的struct可以在C++中等同類(lèi)來(lái)使用,struct和類(lèi)的差別是,struct的成員默認(rèn)訪問(wèn)修飾符是public,而類(lèi)默認(rèn)是private。
4、C++支持重載,而C不支持重載,C++支持重載在于C++名字的修飾符與C不同,例如在C++中函數(shù) int f(int) 經(jīng)過(guò)名字修飾之后變?yōu)開(kāi)f_int,而C是_f,所以C++才會(huì)支持不同的參數(shù)調(diào)用不同的函數(shù)。
5、C++中有引用,而C沒(méi)有。那指針和引用有什么差別?
指針和引用的區(qū)別:
①指針有自己的一塊空間,而引用只是一個(gè)別名。
②使用sizeof查看一個(gè)指針大小為4(32位),而引用的大小是被引用對(duì)象的大小。
③指針可以是NULL,而引用必須被初始化且必須是對(duì)一個(gè)以初始化對(duì)象的引用。
④作為參數(shù)傳遞時(shí),指針需要被解引用才可以對(duì)對(duì)象進(jìn)行操作,而直接對(duì)引用的修改都會(huì)改變引用所指向的對(duì)象。
⑤指針在使用中可以指向其它對(duì)象,但是引用只能是一個(gè)對(duì)象的引用,不能被修改。
⑥指針可以有多級(jí)指針(**p),而引用只有一級(jí)。
⑦指針和引用使用++運(yùn)算符的意義不一樣。
6、C++全部變量的默認(rèn)連接屬性是外連接,而C是內(nèi)連接。
7、C中用const修飾的變量不可以用在定義數(shù)組時(shí)的大小,但是C++用const修飾的變量可以。(如果不進(jìn)行&,解引用的操作的話,是存放在符號(hào)表的,不開(kāi)辟內(nèi)存)
8、C++有很多特有的輸入輸出流。

?

91、 C++中NULL和nullptr的區(qū)別

1.在C語(yǔ)言中,NULL通常被定義為:
#define NULL ((void *)0)
所以說(shuō)NULL實(shí)際上是一個(gè)空指針。
2.C++是強(qiáng)類(lèi)型語(yǔ)言,void*是不能隱式轉(zhuǎn)換成其他類(lèi)型的指針的,所以實(shí)際上編譯器提供的頭文件做了相應(yīng)的處理:
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
可見(jiàn),在C++中,NULL實(shí)際上是0。
3.C++中的nullptr
就是空指針常量,C++11之前并沒(méi)有所謂的“空指針類(lèi)型”,C++11設(shè)計(jì)了nullptr_t,它唯一接受的值就是nullptr,專(zhuān)門(mén)代表空指針。

92、 C/C++內(nèi)存分配

1、靜態(tài)存儲(chǔ)區(qū)分配
內(nèi)存分配在程序編譯之前完成,且在程序的整個(gè)運(yùn)行期間都存在,例如全局變量、靜態(tài)變量等。
2、棧上分配
在函數(shù)執(zhí)行時(shí),函數(shù)內(nèi)的局部變量的存儲(chǔ)單元在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí)這些存儲(chǔ)單元自動(dòng)釋放。
3、堆上分配
堆分配(又稱(chēng)動(dòng)態(tài)內(nèi)存分配)。程序在運(yùn)行時(shí)用malloc或者new申請(qǐng)內(nèi)存,程序員自己用free或者delete釋放,動(dòng)態(tài)內(nèi)存的生存期由我們自己決定。

93、 c/c++的內(nèi)存分配模型,詳細(xì)說(shuō)一下棧、堆、靜態(tài)存儲(chǔ)區(qū)?

1、棧區(qū)(stack),由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等其操作方式類(lèi)似于數(shù)據(jù)結(jié)構(gòu)中的棧。
2、堆區(qū)(heap),一般由程序員分配釋放,若程序員不釋放,程序結(jié)束時(shí)可能由OS(操作系統(tǒng))回收。注意它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事,分配方式倒是類(lèi)似于鏈表。
3、全局區(qū)(靜態(tài)區(qū))(static),全局變量和靜態(tài)變量的存儲(chǔ)是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域,未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。程序結(jié)束后由系統(tǒng)釋放。
4、常量存儲(chǔ)區(qū),常量字符串就是放在這里的。程序結(jié)束后由系統(tǒng)釋放。
5、程序代碼區(qū),存放函數(shù)體的二進(jìn)制代碼。

94、 野指針是什么?如何檢測(cè)內(nèi)存泄漏?

1.野指針:指向內(nèi)存被釋放的內(nèi)存或者沒(méi)有訪問(wèn)權(quán)限的內(nèi)存的指針。
2.“野指針”的成因主要有3種:
○1指針變量沒(méi)有被初始化。任何指針變量剛被創(chuàng)建時(shí)不會(huì)自動(dòng)成為NULL指針,它的缺省值是隨機(jī)的,它會(huì)亂指一氣。所以,指針變量在創(chuàng)建的同時(shí)應(yīng)當(dāng)被初始化,要么將指針設(shè)置為NULL,要么讓它指向合法的內(nèi)存。例如char *p = NULL;char *str = new char(100);
○2指針p被free或者delete之后,沒(méi)有置為NULL;
○3指針操作超越了變量的作用范圍。
3.如何避免野指針:
○1對(duì)指針進(jìn)行初始化
①將指針初始化為NULL。
char *p = NULL;
②用malloc分配內(nèi)存
char * p = (char * )malloc(sizeof(char));
③用已有合法的可訪問(wèn)的內(nèi)存地址對(duì)指針初始化
char num[ 30] = {0};
char *p = num;
○2指針用完后釋放內(nèi)存,將指針賦NULL。
delete(p);
p = NULL;

95、 懸空指針和野指針有什么區(qū)別?

1.野指針:野指針指,訪問(wèn)一個(gè)已刪除或訪問(wèn)受限的內(nèi)存區(qū)域的指針,野指針不能判斷是否為NULL來(lái)避免。指針沒(méi)有初始化,釋放后沒(méi)有置空,越界
2.懸空指針:一個(gè)指針的指向?qū)ο笠驯粍h除,那么就成了懸空指針。野指針是那些未初始化的指針。

96、 內(nèi)存泄漏

1.內(nèi)存泄漏
內(nèi)存泄漏是指由于疏忽或錯(cuò)誤造成了程序未能釋放掉不再使用的內(nèi)存的情況。內(nèi)存泄漏并非指內(nèi)存在物理上消失,而是應(yīng)用程序分配某塊內(nèi)存后,由于設(shè)計(jì)錯(cuò)誤,失去了對(duì)該段內(nèi)存的控制;或者申請(qǐng)了?塊內(nèi)存空間,使?完畢后沒(méi)有釋放掉,或者由程序申請(qǐng)的?塊內(nèi)存,且沒(méi)有任何?個(gè)指針指向它,那么這塊內(nèi)存就泄漏了。?般表現(xiàn)?式是程序運(yùn)?時(shí)間越?,占?內(nèi)存越多,最終?盡全部?jī)?nèi)存,整個(gè)系統(tǒng)崩潰。
2.內(nèi)存泄漏的后果
只發(fā)生一次小的內(nèi)存泄漏可能不被注意,但泄漏大量?jī)?nèi)存的程序?qū)?huì)出現(xiàn)各種征兆:性能下降到內(nèi)存逐漸用完,導(dǎo)致另一個(gè)程序失敗,而使用戶無(wú)從查找問(wèn)題的真正根源。
3.內(nèi)存泄漏類(lèi)型
(1)堆內(nèi)存泄漏 (Heap leak)。對(duì)內(nèi)存指的是程序運(yùn)行中根據(jù)需要分配通過(guò)malloc,realloc new等從堆中分配的一塊內(nèi)存,再是完成后必須通過(guò)調(diào)用對(duì)應(yīng)的 free或者delete 刪掉。如果程序的設(shè)計(jì)的錯(cuò)誤導(dǎo)致這部分內(nèi)存沒(méi)有被釋放,那么此后這塊內(nèi)存將不會(huì)被使用,就會(huì)產(chǎn)生Heap Leak.
(2)系統(tǒng)資源泄露(Resource Leak)。主要指程序使用系統(tǒng)分配的資源比如 Bitmap,handle ,SOCKET等沒(méi)有使用相應(yīng)的函數(shù)釋放掉,導(dǎo)致系統(tǒng)資源的浪費(fèi),嚴(yán)重可導(dǎo)致系統(tǒng)效能降低,系統(tǒng)運(yùn)行不穩(wěn)定。
4.如何排除
使用工具軟件BoundsChecker,BoundsChecker是一個(gè)運(yùn)行時(shí)錯(cuò)誤檢測(cè)工具,它主要定位程序運(yùn)行時(shí)期發(fā)生的各種錯(cuò)誤;
調(diào)試運(yùn)行DEBUG版程序,運(yùn)用以下技術(shù):CRT(C run-time libraries)、運(yùn)行時(shí)函數(shù)調(diào)用堆棧、內(nèi)存泄漏時(shí)提示的內(nèi)存分配序號(hào)(集成開(kāi)發(fā)環(huán)境OUTPUT窗口),綜合分析內(nèi)存泄漏的原因,排除內(nèi)存泄漏。
5.解決方法
智能指針。
6.檢查、定位內(nèi)存泄漏
1.window上檢查方法:在main函數(shù)最后面一行,加上一句_CrtDumpMemoryLeaks()。調(diào)試程序,自然關(guān)閉程序讓其退出,查看輸出:
輸出這樣的格式{453}normal block at 0x02432CA8,868 bytes long
被{}包圍的453就是我們需要的內(nèi)存泄漏定位值,868 bytes long就是說(shuō)這個(gè)地方有868比特內(nèi)存沒(méi)有釋放。
定位代碼位置
在main函數(shù)第一行加上_CrtSetBreakAlloc(453);意思就是在申請(qǐng)453這塊內(nèi)存的位置中斷。然后調(diào)試程序,程序中斷了,查看調(diào)用堆棧。加上頭文件#include <crtdbg.h>
2.linux:?先可以通過(guò)觀察猜測(cè)是否可能發(fā)?內(nèi)存泄漏,Linux中使? swap 命令觀察還有多少可?的交換空間,在?兩分鐘內(nèi)鍵?該命令三到四次,看看可?的交換區(qū)是否在減少。
3.還可以使?其他?些 /usr/bin/stat ?具如 netstat、 vmstat 等。如發(fā)現(xiàn)波段有內(nèi)存被分配且從不釋放,?個(gè)可能的解釋就是有個(gè)進(jìn)程出現(xiàn)了內(nèi)存泄漏。
3.?于內(nèi)存調(diào)試,內(nèi)存泄漏檢測(cè)以及性能分析的軟件開(kāi)發(fā)?具 valgrind 這樣的?具來(lái)進(jìn)?內(nèi)存泄漏的檢測(cè)。

97、 內(nèi)存溢出定位

如果是Windows,考慮下Visual Leak Detector,這個(gè)對(duì)泄露點(diǎn)信息定位相當(dāng)不錯(cuò);如果是Linux,考慮下Valgrind,檢測(cè)內(nèi)存使用以及線程方面的Bug功能非常強(qiáng)大

98、 什么是內(nèi)存對(duì)齊

現(xiàn)在計(jì)算機(jī)內(nèi)存空間都是按照byte字節(jié)劃分的,理論上講對(duì)任何類(lèi)型的變量的訪問(wèn)可以從任何地址開(kāi)始,但實(shí)際情況是在訪問(wèn)特定類(lèi)型變量的時(shí)候經(jīng)常在特定的內(nèi)存地址上訪問(wèn),這就需要各種數(shù)據(jù)類(lèi)型按照一定的規(guī)則在空間上排列,而不是一個(gè)接一個(gè)的排放,這就是內(nèi)存對(duì)齊。

99、 為什么內(nèi)存對(duì)齊

1.平臺(tái)原因(移植原因)
2.不是所有的硬件平臺(tái)都能訪問(wèn)任意地址上的任意數(shù)據(jù)的;
3.某些硬件平臺(tái)只能在某些地址處取某些特定類(lèi)型的數(shù)據(jù),否則拋出硬件異
4.性能原因:
○1數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能地在自然邊界上對(duì)齊。
○2原因在于,為了訪問(wèn)未對(duì)齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問(wèn);而對(duì)齊的內(nèi)存訪問(wèn)僅需要一次訪問(wèn)。

100、 內(nèi)存對(duì)齊規(guī)則

在不用#pagrama pack()包裹的情況下,結(jié)構(gòu)體或聯(lián)合體按照編譯器默認(rèn)的對(duì)齊方式有以下三個(gè)對(duì)其原則:
1.數(shù)據(jù)成員對(duì)齊原則:結(jié)構(gòu)(struct或union)的數(shù)據(jù)成員,第一個(gè)數(shù)據(jù)成員存放在offset為0的地方,以后每個(gè)數(shù)據(jù)成員存儲(chǔ)的起始位置都要從其占用內(nèi)存大小的整數(shù)倍開(kāi)始。
2.結(jié)構(gòu)體作為成員的原則:如果一個(gè)結(jié)構(gòu)中有某些結(jié)構(gòu)體成員,則結(jié)構(gòu)的成員要從其內(nèi)部最大元素大小的整數(shù)倍地址開(kāi)始存儲(chǔ)。(struct a里有struct b,b里有char,int,double等元素,那b應(yīng)該從8的整數(shù)倍開(kāi)始,當(dāng)然了,如果struct b在結(jié)構(gòu)體a開(kāi)始位置,則直接考慮其大小)
3.結(jié)構(gòu)(或聯(lián)合)的整體對(duì)齊原則:在數(shù)據(jù)成員各自對(duì)齊后,結(jié)構(gòu)(或聯(lián)合)本身也要進(jìn)行對(duì)齊,即以結(jié)構(gòu)體內(nèi)部占用內(nèi)存空間最大的數(shù)據(jù)類(lèi)型進(jìn)行對(duì)齊。(等同于sizeof該結(jié)構(gòu)體的結(jié)果必須是其內(nèi)部最大成員占用內(nèi)存的整數(shù)倍)。
示例1:

struct mystruct { char a;//偏移量為0;a占用一個(gè)字節(jié) double b;//下一個(gè)可用地址偏移量為1,不是sizeof(double)=8的整數(shù)倍,需要補(bǔ)7個(gè)字節(jié) int c;//下一個(gè)可用地址偏移量為1+7+8=16,是sizeof(int)=4的整數(shù)倍,滿足Int的對(duì)齊方式 }//所有成員變量都分配了空間,空間大小=1+7+8+4=20,不是最大空間類(lèi)型double的整數(shù)倍,所以需要填充4個(gè)字節(jié)以滿足結(jié)構(gòu)體大小為sizeof(double)=8的整數(shù)倍 sizeof(mystruct)=24;

示例2:

struct B { int a; char b; int c; }; struct A { char x1; B b; short x2; float x3; char x4; }aa; //#pragma pack() int main() { printf("%d\n", sizeof(struct A)); //printf("%x,%x,%x\n", aa.a, *(&aa.b + 1), aa.c); //printf("%p,%p,%p\n", &aa.a, &aa.b, &aa.c); return 0; }

添加了#pragma pack(n)后規(guī)則就變成了下面這樣:
1、 偏移量要是n和當(dāng)前變量大小中較小值的整數(shù)倍
2、 整體大小要是n和最大變量大小中較小值的整數(shù)倍
3、 n值必須為1,2,4,8…,為其他值時(shí)就按照默認(rèn)的分配規(guī)則

總結(jié)

以上是生活随笔為你收集整理的二十万字C/C++、嵌入式软开面试题全集宝典五的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。