首页 > 试题广场 >

当程序运行时,如果遇到引用空指针、下标越界或显式调用pani

[单选题]
当程序运行时,如果遇到引用空指针、下标越界或显式调用panic函数等情况,则先触发panic函数的执行,然后调用延迟函数。调用者继续传递panic,因此该过程一直在调用栈中重复发生:函数停止执行,调用延迟执行函数。如果一路在延迟函数中没有recover函数的调用,则会到达该协程的起点,该协程结束,然后终止其他所有协程,其他协程的终止过程也是重复发生:函数停止执行,调用延迟执行函数。这一说法是否正确。
  • true
  • false
当内置的panic()函数调用时,外围函数或方法的执行会立即终止。然后,任何延迟执行(defer)的函数或方法都会被调用,就像其外围函数正常返回一样。最后,调用返回到该外围函数的调用者,就像该外围调用函数或方法调用了panic()一样,因此该过程一直在调用栈中重复发生:函数停止执行,调用延迟执行函数等。当到达main()函数时不再有可以返回的调用者,因此这个过程会终止,并将包含传入原始panic()函数中的值的调用栈信息输出到os.Stderr。
发表于 2018-04-11 09:12:19 回复(0)
更多回答
panic需要等defer结束后才会向上传递。出现panic的时候,会先按照defer的**先出的顺序执行,最后才会执行panic。
发表于 2018-02-27 16:34:31 回复(4)
前面说的都没问题,出问题的是这句话:”该协程结束,然后终止其他所有协程,其他协程的终止过程也是重复发生:函数停止执行,调用延迟执行函数。这一说法是否正确。“
协程会遍历所有调用栈上需要执行的defer,如果执行完这些defer没有遇到recover,会直接调用exit退出程序
发表于 2019-03-02 18:49:54 回复(0)
func main() {
	defer func() {
		fmt.Println("【主goroutine】执行延迟函数")
		r := recover()
		fmt.Printf("【主goroutine】捕获到异常了:%v\n",r)
	}()
	go func() {
		defer func() {
			fmt.Printf("【goroutine1】执行延迟函数\n")
		}()
		time.Sleep(2*time.Second)
		panic("【goroutine1】发生panic调用")
		fmt.Println("【goroutine1】发生奔溃后还能继续执行嘛")
	}()
	go func() {
		defer func() {
			fmt.Println("【goroutine2】执行延迟函数")
			r := recover()
			fmt.Printf("【goroutine2】捕获到异常了:%v\n",r)
		}()
		for i := 0; i< 100; i++{
			fmt.Printf("【goroutine2】第%d次循环\n",i)
			time.Sleep(1*time.Second)
		}
	}()
	for i := 0; i< 100; i++{
		fmt.Printf("【主goroutine】第%d次循环\n",i)
		time.Sleep(1*time.Second)
	}
}


输出结果:
【主goroutine】第0次循环
【goroutine2】第0次循环
【goroutine2】第1次循环
【主goroutine】第1次循环
【主goroutine】第2次循环
【goroutine2】第2次循环
【goroutine1】执行延迟函数
panic: 【goroutine1】发生panic调用

goroutine 6 [running]:
main.main.func2()
	C:/newuser/go/src/customServer/file.go:115 +0x6f
created by main.main
	C:/newuser/go/src/customServer/file.go:110 +0x65
结论:
无法通过在延迟函数中调用recover函数来捕获其他goroutien中的未捕获的崩溃。
当一个goroutine中发生崩溃,该goroutine的所有嵌套的延迟函数按倒序执行,如果一直到该goroutine的起点都没能捕获这个崩溃,其他goroutine包括主goroutine都无法捕获且也无法调用延迟函数,整个程序直接崩溃。
发表于 2021-05-11 11:18:46 回复(3)
牛客网做题心得:题目屁话特多的必错,判断题大部分都是错的.
发表于 2019-07-04 11:19:31 回复(0)
先调用defer  才执行panic  如果没有recover 程序就会终止
发表于 2019-07-04 13:33:10 回复(0)
反了,先调用defer,再Panic
发表于 2017-12-22 01:07:19 回复(0)
题目错误地方是其他协程不会执行延迟函数(如果不是正好运行到延迟函数的话)
总结一下:
  1. panic的意义是在该位置生成一个中断事件(没有立即被进程捕获)
  2. 中断事件生成后采取执行延迟函数
  3. panic所在协程会执行调用栈内每层的延迟函数,直到被捕获
  4. 进程捕获到中断事件时,停止其他协程的执行
  5. 在事件产生到被捕获期间其他协程正常运行
  6. panic协程延迟函数如果有死锁等东西阻碍不能运行结束的话,中断事件不会被进程捕获
  7. recover不会捕获其他协程的panic
  8. 最后panic和堆栈信息是进程捕获中断后打出的
编辑于 2023-01-31 12:20:32 回复(0)
panic需要等defer结束后才会向上传递。出现panic的时候,会先按照defer的后进先出的顺序执行,最后才会执行panic。

发表于 2024-09-13 15:26:16 回复(0)
当内置的panic()函数调用时,外围函数或方法的执行会立即终止。然后,任何延迟执行(defer)的函数或方法都会被调用,就像其外围函数正常返回一样。最后,调用返回到该外围函数的调用者,就像该外围调用函数或方法调用了panic()一样,因此该过程一直在调用栈中重复发生:函数停止执行,调用延迟执行函数等。当到达main()函数时不再有可以返回的调用者,因此这个过程会终止,并将包含传入原始panic()函数中的值的调用栈信息输出到os.Stderr。
发表于 2021-02-26 12:31:55 回复(0)
panic需要等待defer调用结束后才会向上传递,即出现了panic先执行defer,执行完defer后才执行panic
发表于 2023-07-09 13:53:53 回复(0)

啥玩意,没发现哪里不对啊,感觉题目里说的花里胡哨的。。。先执行panic吧,不然怎么遇到panic就直接终止函数的正常顺序执行了,到底是panic的作用还是编译器的处理,todo一哈,后续深入学一下,panic函数的作用。

发表于 2019-08-07 20:42:15 回复(0)
先调用延迟函数,再触发panic()
发表于 2018-11-18 09:02:33 回复(0)