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

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

前沿拓展:

索引越界

索引越界是貼吧

主要功能是百度貼吧伴侶注冊賬號的申請、計算吧友排名等

(詳見索引越界吧置頂貼

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

我也在用


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

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

前導(dǎo)知識:運行時恐慌 panic

這種程序異常被叫做 panic,我把它翻譯為運行時恐慌。其中的“恐慌”二字是由 panic 直譯過來的,而之所以前面又加上了“運行時”三個字,是因為這種異常只會在程序運行的時候被拋出來。

我們舉個具體的例子來看看。

比如說,一個 Go 程序里有一個切片,它的長度是 5,也就是說該切片中的元素值的索引分別為0、1、2、3、4,但是,我在程序里卻想通過索引5訪問其中的元素值,顯而易見,這樣的訪問是不正確的。

package main

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

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

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

現(xiàn)在,就讓我們來看一下這樣的 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”的含義是,這是一個runtime代碼包中拋出的 panic。在這個 panic 中,包含了一個runtime.Error接口類型的值。runtime.Error接口內(nèi)嵌了error接口,并做了一點點擴展,runtime包中有不少它的實現(xiàn)類型。

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

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

注意,這里的 ID 其實并不重要,因為它只是 Go 語言運行時系統(tǒng)內(nèi)部給予的一個 goroutine 編號,我們在程序中是無法獲取和更改的。

我們再看下一行,“main.main()”表明了這個 goroutine 包裝的go函數(shù)就是命令源碼文件中的那個main函數(shù),也就是說這里的 goroutine 正是主 goroutine。再下面的一行,指出的就是這個 goroutine 中的哪一行代碼在此 panic 被引發(fā)時正在執(zhí)行。

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

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

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

那么,我的第一個問題也隨之而來了。我今天的問題是:

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

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

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

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

問題解析

panic 可能是我們在無意間(或者說一不小心)引發(fā)的,如前文所述的索引越界。這類 panic 是真正的、在我們意料之外的程序異常。不過,除此之外,我們還是可以有意地引發(fā) panic。

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

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

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

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

為了更清楚地展示**中描述的過程,我編寫了 demo48.go 文件。你可以先查看一下其中的代碼,再試著運行它,并體會它打印的內(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.")
}

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

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

比如,main函數(shù)調(diào)用了caller1函數(shù),而caller1函數(shù)又調(diào)用了caller2函數(shù),那么caller2函數(shù)中代碼的執(zhí)行信息會先出現(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)對 panic 被引發(fā)后的程序終止過程有一定的了解了。深入地了解此過程,以及正確地解讀 panic 詳情應(yīng)該是我們的必備技能,這在調(diào)試 Go 程序或者為 Go 程序排查錯誤的時候非常重要。

小編綜合來說

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

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

思考題

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

筆記源碼

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

拓展知識:

索引越界

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

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

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

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

索引:

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

索引的優(yōu)點:

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

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

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

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

數(shù)組:

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

索引越界

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

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

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

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

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

確保它在添加之后不會超出界限。

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我可以得到一個索引超出邊界錯誤在代碼中指出的點。我不確定我哪里會出問題,因為一切都還在19的范圍內(nèi)。

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

索引越界

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

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

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

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

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

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