久久亚洲精品国产精品_羞羞漫画在线版免费阅读网页漫画_国产精品久久久久久久久久久久_午夜dj免费观看在线视频_希崎杰西卡番号

索引越界(索引越界和空指針異常)

前沿拓展:

索引越界

索引越界是貼吧

主要功能是百度貼吧伴侶注冊(cè)賬號(hào)的申請(qǐng)、計(jì)算吧友排名等

(詳見(jiàn)索引越界吧置頂貼

百度貼吧伴侶就是可以在貼子后面加上文簽圖簽的一款軟件

我也在用


21 | panic函數(shù)、recover函數(shù)以及defer語(yǔ)句 (上)

在本篇,我要給你展示 Go 語(yǔ)言的另外一種錯(cuò)誤處理方式。不過(guò),嚴(yán)格來(lái)說(shuō),它處理的不是錯(cuò)誤,而是異常,并且是一種在我們意料之外的程序異常。

前導(dǎo)知識(shí):運(yùn)行時(shí)恐慌 panic

這種程序異常被叫做 panic,我把它翻譯為運(yùn)行時(shí)恐慌。其中的“恐慌”二字是由 panic 直譯過(guò)來(lái)的,而之所以前面又加上了“運(yùn)行時(shí)”三個(gè)字,是因?yàn)檫@種異常只會(huì)在程序運(yùn)行的時(shí)候被拋出來(lái)。

我們舉個(gè)具體的例子來(lái)看看。

比如說(shuō),一個(gè) Go 程序里有一個(gè)切片,它的長(zhǎng)度是 5,也就是說(shuō)該切片中的元素值的索引分別為0、1、2、3、4,但是,我在程序里卻想通過(guò)索引5訪問(wèn)其中的元素值,顯而易見(jiàn),這樣的訪問(wèn)是不正確的。

package main

func main() {
s1 := []int{0, 1, 2, 3, 4}
e5 := s1[5]
_ = e5
}

Go 程序,確切地說(shuō)是程序內(nèi)嵌的 Go 語(yǔ)言運(yùn)行時(shí)系統(tǒng),會(huì)在執(zhí)行到這行代碼的時(shí)候拋出一個(gè)“index out of range”的 panic,用以提示你索引越界了。

當(dāng)然了,這不僅僅是個(gè)提示。當(dāng) panic 被拋出之后,如果我們沒(méi)有在程序里添加任何保護(hù)措施的話,程序(或者說(shuō)代表它的那個(gè)進(jìn)程)就會(huì)在打印出 panic 的詳細(xì)情況(以下簡(jiǎn)稱(chēng) panic 詳情)之后,終止運(yùn)行。

現(xiàn)在,就讓我們來(lái)看一下這樣的 panic 詳情中都有什么。

panic: runtime error: index out of range

goroutine 1 [running]:
main.main()
/Users/haolin/GeekTime/Golang_Puzzlers/src/puzzlers/article19/q0/demo47.go:5 +0x3d
exit status 2

這份詳情的第一行是“panic: runtime error: index out of range”。其中的“runtime error”的含義是,這是一個(gè)runtime代碼包中拋出的 panic。在這個(gè) panic 中,包含了一個(gè)runtime.Error接口類(lèi)型的值。runtime.Error接口內(nèi)嵌了error接口,并做了一點(diǎn)點(diǎn)擴(kuò)展,runtime包中有不少它的實(shí)現(xiàn)類(lèi)型。

實(shí)際上,此詳情中的“panic:”右邊的內(nèi)容,正是這個(gè) panic 包含的runtime.Error類(lèi)型值的字符串表示形式。

此外,panic 詳情中,一般還會(huì)包含與它的引發(fā)原因有關(guān)的 goroutine 的代碼執(zhí)行信息。正如前述詳情中的“goroutine 1 [running]”,它表示有一個(gè) ID 為1的 goroutine 在此 panic 被引發(fā)的時(shí)候正在運(yùn)行。

注意,這里的 ID 其實(shí)并不重要,因?yàn)樗皇?Go 語(yǔ)言運(yùn)行時(shí)系統(tǒng)內(nèi)部給予的一個(gè) goroutine 編號(hào),我們?cè)诔绦蛑惺菬o(wú)法獲取和更改的。

我們?cè)倏聪乱恍校癿ain.main()”表明了這個(gè) goroutine 包裝的go函數(shù)就是命令源碼文件中的那個(gè)main函數(shù),也就是說(shuō)這里的 goroutine 正是主 goroutine。再下面的一行,指出的就是這個(gè) goroutine 中的哪一行代碼在此 panic 被引發(fā)時(shí)正在執(zhí)行。

這包含了此行代碼在其所屬的源碼文件中的行數(shù),以及這個(gè)源碼文件的絕對(duì)路徑。這一行最后的+0x3d代表的是:此行代碼相對(duì)于其所屬函數(shù)的入口程序計(jì)數(shù)偏移量。不過(guò),一般情況下它的用處并不大。

最后,“exit status 2”表明我的這個(gè)程序是以退出狀態(tài)碼2結(jié)束運(yùn)行的。在大多數(shù)**作系統(tǒng)中,只要退出狀態(tài)碼不是0,都意味著程序運(yùn)行的非正常結(jié)束。在 Go 語(yǔ)言中,因 panic 導(dǎo)致程序結(jié)束運(yùn)行的退出狀態(tài)碼一般都會(huì)是2。

綜上所述,我們從上邊的這個(gè) panic 詳情可以看出,作為此 panic 的引發(fā)根源的代碼處于 demo47.go 文件中的第 5 行,同時(shí)被包含在main包(也就是命令源碼文件所在的代碼包)的main函數(shù)中。

那么,我的第一個(gè)問(wèn)題也隨之而來(lái)了。我今天的問(wèn)題是:

我們先說(shuō)一個(gè)大致的過(guò)程:某個(gè)函數(shù)中的某行代碼有意或無(wú)意地引發(fā)了一個(gè) panic。這時(shí),初始的 panic 詳情會(huì)被建立起來(lái),并且該程序的控制權(quán)會(huì)立即從此行代碼轉(zhuǎn)移至調(diào)用其所屬函數(shù)的那行代碼上,也就是調(diào)用棧中的上一級(jí)。

這也意味著,此行代碼所屬函數(shù)的執(zhí)行隨即終止。緊接著,控制權(quán)并不會(huì)在此有片刻的停留,它又會(huì)立即轉(zhuǎn)移至再上一級(jí)的調(diào)用代碼處。控制權(quán)如此一級(jí)一級(jí)地沿著調(diào)用棧的反方向傳播至頂端,也就是我們編寫(xiě)的最外層函數(shù)那里。

這里的最外層函數(shù)指的是go函數(shù),對(duì)于主 goroutine 來(lái)說(shuō)就是main函數(shù)。但是控制權(quán)也不會(huì)停留在那里,而是被 Go 語(yǔ)言運(yùn)行時(shí)系統(tǒng)收回。

隨后,程序崩潰并終止運(yùn)行,承載程序這次運(yùn)行的進(jìn)程也會(huì)隨之**亡并消失。與此同時(shí),在這個(gè)控制權(quán)傳播的過(guò)程中,panic 詳情會(huì)被逐漸地積累和完善,并會(huì)在程序終止之前被打印出來(lái)。

問(wèn)題解析

panic 可能是我們?cè)跓o(wú)意間(或者說(shuō)一不小心)引發(fā)的,如前文所述的索引越界。這類(lèi) panic 是真正的、在我們意料之外的程序異常。不過(guò),除此之外,我們還是可以有意地引發(fā) panic。

Go 語(yǔ)言的內(nèi)建函數(shù)panic是專(zhuān)門(mén)用于引發(fā) panic 的。panic函數(shù)使程序開(kāi)發(fā)者可以在程序運(yùn)行期間報(bào)告異常。

注意,這與從函數(shù)返回錯(cuò)誤值的意義是完全不同的。當(dāng)我們的函數(shù)返回一個(gè)非nil的錯(cuò)誤值時(shí),函數(shù)的調(diào)用方有權(quán)選擇不處理,并且不處理的后果往往是不致命的。

這里的“不致命”的意思是,不至于使程序無(wú)法提供任何功能(也可以說(shuō)僵**)或者直接崩潰并終止運(yùn)行(也就是真**)。

但是,當(dāng)一個(gè) panic 發(fā)生時(shí),如果我們不施加任何保護(hù)措施,那么導(dǎo)致的直接后果就是程序崩潰,就像前面描述的那樣,這顯然是致命的。

為了更清楚地展示**中描述的過(guò)程,我編寫(xiě)了 demo48.go 文件。你可以先查看一下其中的代碼,再試著運(yùn)行它,并體會(huì)它打印的內(nèi)容所代表的含義。

package main

import (
"fmt"
)

func main() {
fmt.Println("Enter function main.")
caller1()
fmt.Println("Exit function main.")
}

func caller1() {
fmt.Println("Enter function caller1.")
caller2()
fmt.Println("Exit function caller1.")
}

func caller2() {
fmt.Println("Enter function caller2.")
s1 := []int{0, 1, 2, 3, 4}
e5 := s1[5]
_ = e5
fmt.Println("Exit function caller2.")
}

我在這里再提示一點(diǎn)。panic 詳情會(huì)在控制權(quán)傳播的過(guò)程中,被逐漸地積累和完善,并且,控制權(quán)會(huì)一級(jí)一級(jí)地沿著調(diào)用棧的反方向傳播至頂端。

因此,在針對(duì)某個(gè) goroutine 的代碼執(zhí)行信息中,調(diào)用棧底端的信息會(huì)先出現(xiàn),第二是上一級(jí)調(diào)用的信息,以此類(lèi)推,最后才是此調(diào)用棧頂端的信息。

比如,main函數(shù)調(diào)用了caller1函數(shù),而caller1函數(shù)又調(diào)用了caller2函數(shù),那么caller2函數(shù)中代碼的執(zhí)行信息會(huì)先出現(xiàn),第二是caller1函數(shù)中代碼的執(zhí)行信息,最后才是main函數(shù)的信息。

goroutine 1 [running]:
main.caller2()
/Users/haolin/GeekTime/Golang_Puzzlers/src/puzzlers/article19/q1/demo48.go:22 +0x91
main.caller1()
/Users/haolin/GeekTime/Golang_Puzzlers/src/puzzlers/article19/q1/demo48.go:15 +0x66
main.main()
/Users/haolin/GeekTime/Golang_Puzzlers/src/puzzlers/article19/q1/demo48.go:9 +0x66
exit status 2
索引越界(索引越界和空指針異常)

(從 panic 到程序崩潰)

好了,到這里,我相信你已經(jīng)對(duì) panic 被引發(fā)后的程序終止過(guò)程有一定的了解了。深入地了解此過(guò)程,以及正確地解讀 panic 詳情應(yīng)該是我們的必備技能,這在調(diào)試 Go 程序或者為 Go 程序排查錯(cuò)誤的時(shí)候非常重要。

小編綜合來(lái)說(shuō)

最近的兩篇文章,我們是圍繞著 panic 函數(shù)、recover 函數(shù)以及 defer 語(yǔ)句進(jìn)行的。今天我主要講了 panic 函數(shù)。這個(gè)函數(shù)是專(zhuān)門(mén)被用來(lái)引發(fā) panic 的。panic 也可以被稱(chēng)為運(yùn)行時(shí)恐慌,它是一種只能在程序運(yùn)行期間拋出的程序異常。

Go 語(yǔ)言的運(yùn)行時(shí)系統(tǒng)可能會(huì)在程序出現(xiàn)嚴(yán)重錯(cuò)誤時(shí)自動(dòng)地拋出 panic,我們?cè)谛枰獣r(shí)也可以通過(guò)調(diào)用panic函數(shù)引發(fā) panic。但不論怎樣,如果不加以處理,panic 就會(huì)導(dǎo)致程序崩潰并終止運(yùn)行。

思考題

一個(gè)函數(shù)怎樣才能把 panic 轉(zhuǎn)化為error類(lèi)型值,并將其作為函數(shù)的結(jié)果值返回給調(diào)用方?

筆記源碼

https://github.com/MingsonZheng/go-core-demo

拓展知識(shí):

索引越界

限制索引取值范圍(0到 (數(shù)組長(zhǎng)度-1)),或者增加數(shù)組的長(zhǎng)度。

數(shù)組元素用整個(gè)數(shù)組的名字和它自己在數(shù)組中的順序位置來(lái)表示。例如,a[0]表示名字為a的數(shù)組中的第一個(gè)元素,a[1]代表數(shù)組a的第二個(gè)元素,以此類(lèi)推。
數(shù)組是通過(guò)下表進(jìn)行訪問(wèn),但超出下標(biāo)(索引)最大值(數(shù)組長(zhǎng)度-1)就會(huì)訪問(wèn)超出界限。

如:int [] arr= new int[2];;
arr[0]=1;
arr[1]=2;

此數(shù)組長(zhǎng)度為2,下標(biāo)最大為1(數(shù)組下標(biāo)從0開(kāi)始。
如果下標(biāo)超出0-1這個(gè)范圍就會(huì)出現(xiàn)索引超出界限問(wèn)題。
限制下標(biāo)(索引)的取值范圍,或者數(shù)組長(zhǎng)度增加都可以防止索引超出界限。

索引:

在數(shù)據(jù)庫(kù)關(guān)系圖中,可以在選定表的"索引/鍵"屬性頁(yè)中創(chuàng)建、編輯或刪除每個(gè)索引類(lèi)型。當(dāng)保存索引所附加到的表,或保存該表所在的關(guān)系圖時(shí),索引將保存在數(shù)據(jù)庫(kù)中。

索引的優(yōu)點(diǎn):

1、大大加快數(shù)據(jù)的檢索速度;

2、創(chuàng)建唯一性索引,保證數(shù)據(jù)庫(kù)表中每一行數(shù)據(jù)的唯一性;

3、加速表和表之間的連接;

4、在使用分組和排序子句進(jìn)行數(shù)據(jù)檢索時(shí),可以顯著減少查詢(xún)中分組和排序的時(shí)間。

數(shù)組:

在C語(yǔ)言中, 數(shù)組 屬于構(gòu)造數(shù)據(jù)類(lèi)型。一個(gè)數(shù)組可以分解為多個(gè)數(shù)組元素,這些數(shù)組元素可以是基本數(shù)據(jù)類(lèi)型或是構(gòu)造類(lèi)型。因此按數(shù)組元素的類(lèi)型不同,數(shù)組又可分為數(shù)值數(shù)組、字符數(shù)組、指針數(shù)組、結(jié)構(gòu)數(shù)組等各種類(lèi)別。

索引越界

索引超出了數(shù)組界限解決方法:

a.connected[i] = vertices[i+1];

稱(chēng)之為索引i+1。這將導(dǎo)致一個(gè)index out of bounds exception。(在你n等于19的例子中:有效索引將是[0-18]。

你的循環(huán)將從0-18開(kāi)始,但是在該行中,它將會(huì)添加一個(gè)18 + 1 = 19,這是一個(gè)無(wú)效索引)在你的循環(huán)中將條件更改為:

for (int i = 0; i<n-1; i+=2){

確保它在添加之后不會(huì)超出界限。

Vertex [] vertices = new Vertex[n]; int [] numbers = new int[n*2]; AdjacencyList[] all = new AdjacencyList [n+1];for (Vertex v : vertices){
System.out.println(v.value);

AdjacencyList a = new AdjacencyList(v);
for (int i = 0; i < n; i += 2)
{

if (numbers[i] == v.value){
a.connected[i] = vertices[i+1];//array index out of bounds exception:19
else { a.connected[i] = v; }
}
all[0] = a; //add the finished adjacency list to the array

}

與n = 19我可以得到一個(gè)索引超出邊界錯(cuò)誤在代碼中指出的點(diǎn)。我不確定我哪里會(huì)出問(wèn)題,因?yàn)橐磺卸歼€在19的范圍內(nèi)。

頂點(diǎn)=頂點(diǎn)列表[1-19],數(shù)字是一個(gè)平坦的邊緣數(shù)組。

索引越界

記得循環(huán)的時(shí)候,下標(biāo)是從0開(kāi)始到N-1,打印出遍歷數(shù)組的索引十分有幫助,注意一下它的循環(huán)條件,也可以加斷點(diǎn)。

出現(xiàn)此類(lèi)問(wèn)題的原因有多方面。小編綜合來(lái)說(shuō)一下我所理解的,數(shù)組的長(zhǎng)度決定了它所能裝載的數(shù)據(jù)的量。還有就是數(shù)組計(jì)數(shù)是從零開(kāi)始的。例如:當(dāng)Srring arr[]==new String[6];如果要往里輸入名字的話就只能輸入六個(gè),多了就是下標(biāo)越界。

另外數(shù)組一般都是與for循環(huán)結(jié)合起來(lái)用,所以用的的時(shí)候要注意一下它的循環(huán)條件。數(shù)組下標(biāo)越界異常:Java.lang.ArrayIndexOutOfBoundsException,這是一個(gè)非常常見(jiàn)的異常,從名字上看是數(shù)組下標(biāo)越界錯(cuò)誤,解決方法就是查看為什么下標(biāo)越界。這種錯(cuò)誤就是字符串索引越界。

當(dāng)處理數(shù)組越界時(shí),打印出遍歷數(shù)組的索引十分有幫助,這樣我們就能夠跟蹤代碼找到為什么索引達(dá)到了一個(gè)非法的值。

所謂的數(shù)組越界,簡(jiǎn)單地講就是指數(shù)組下標(biāo)變量的取值超過(guò)了初始定義時(shí)的大小,導(dǎo)致對(duì)數(shù)組元素的訪問(wèn)出現(xiàn)在數(shù)組的范圍之外,這類(lèi)錯(cuò)誤也是 C 語(yǔ)言程序中最常見(jiàn)的錯(cuò)誤之一。

原創(chuàng)文章,作者:九賢生活小編,如若轉(zhuǎn)載,請(qǐng)注明出處:http://www.cddhlm.com/8911.html