你如何从"并发地图读取和地图写入"的运行时恐慌中恢复?恢复的通常延迟似乎不起作用.这是为什么?
我知道你不应该在并发环境中使用地图,但仍然:如何在这里恢复?
例:
package main
import "time"
var m = make(map[string]string)
func main() {
go func() {
for {
m["x"] = "foo"
}
}()
go func() {
for {
m["x"] = "foo"
}
}()
time.Sleep(1 * time.Second)
}
Run Code Online (Sandbox Code Playgroud)
请添加恢复代码.:)
我有一个嵌套的结构.
type ConfigOne struct {
// Daemon section from config file.
Daemon daemon
}
type daemon struct {
Loglevel int
Logfile string
}
Run Code Online (Sandbox Code Playgroud)
我有一个String() string关于该类型的方法,我试图将嵌套的struct元素作为返回
func (c ConfigOne)String() string{
return fmt.Sprintf("%+v\n", c)
}
Run Code Online (Sandbox Code Playgroud)
当我尝试将其打印为
c := &modules.ConfigOne{}
c.Daemon.Loglevel = 1
c.Daemon.Logfile = "/tmp/test.log"
modules.Logger.Infoln(c.String())
Run Code Online (Sandbox Code Playgroud)
我收到了错误
func (c ConfigOne)String() string{
//return fmt.Sprintf("%+v\n", c.Daemon.Loglevel)
return fmt.Sprintf("%+v\n", c.Daemon)
}
Run Code Online (Sandbox Code Playgroud)
在经历错误之后,我可以看到类似于下面的重复行
2017/03/05 01:28:25 go-consume.go:38: INFO: {Loglevel:1 Logfile:/tmp/test.log}
Run Code Online (Sandbox Code Playgroud)
最后,在临死前,
type ConfigOne struct {
// Daemon section from config file.
Daemon daemon
}
type …Run Code Online (Sandbox Code Playgroud) 我的程序很恐慌,所以我按照它的建议运行RUST_BACKTRACE=1,我得到了这个(只是一个小片段).
1: 0x800c05b5 - std::sys::imp::backtrace::tracing::imp::write::hf33ae72d0baa11ed
at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:42
2: 0x800c22ed - std::panicking::default_hook::{{closure}}::h59672b733cc6a455
at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panicking.rs:351
Run Code Online (Sandbox Code Playgroud)
如果程序发生恐慌,它会停止整个程序,那么我在哪里可以弄清楚它在恐慌的哪一行?
这条线告诉我第42行和第351行有问题吗?
整个回溯都在这张图片上,我觉得将它复制并粘贴在这里会很麻烦.
我从未听说过堆栈跟踪或后跟踪.我正在编译警告,但我不知道调试符号是什么.
我曾经认为,如果goroutine中的恐慌的调用者在恐慌之前完成,它将使其终止程序(延迟恢复没有任何帮助,因为此时还没有发生恐慌),
直到我尝试以下代码:
func fun1() {
fmt.Println("fun1 started")
defer func() {
if err := recover(); err != nil {
fmt.Println("recover in func1")
}
}()
go fun2()
time.Sleep(10 * time.Second) // wait for the boom!
fmt.Println("fun1 ended")
}
func fun2() {
fmt.Println("fun2 started")
time.Sleep(5 * time.Second)
panic("fun2 booom!")
fmt.Println("fun2 ended")
}
Run Code Online (Sandbox Code Playgroud)
我发现无论调用者函数完成与否,如果goroutines开始出现恐慌,调用者的延迟恢复机制都将无济于事。整个程序仍然无效。
所以为什么?理论上,调用者功能仍在运行。当出现紧急情况时,调用者的延迟功能应起作用(包括恢复)。
我们开发的产品之一是用C++和Symbian完成的诺基亚手机的手机应用程序,我们开始在一段时间内因用户44恐慌而"随机"崩溃.
我是Symbian环境的新手,所以我正在寻找工具和建议来帮助找到这个bug的根源.
我可以获得相当于"堆栈跟踪"吗?是否有通用的恐慌捕获代码可以让我对它有所了解?
我一直在尝试解析嵌套的JSON响应而不将信息映射到预定义的结构.
使用空白界面,它会返回:
map[name:My Folder parentId:1 created:2014-10-09T16:32:07+0000 deleted:false description:Sync Dir id:3 links:[map[rel:self entity:folder href:https://web.domain.org/rest/folders/3 id:3] map[href:https://web.domain.org/rest/folders/1 id:1 rel:parent entity:folder] map[entity:user href:https://web.domain.org/rest/users/1 id:1 rel:creator]] modified:2014-12-18T18:07:01+0000 permalink:https://web.domain.org/w/SpJYGQkv syncable:true type:d userId:1]
所以我使用以下内容来浏览此信息:
func NFind(input interface{}, refs...interface{}) (output interface{}) {
defer func() {if r := recover(); r != nil { output = nil }}()
for _, ref := range refs {
switch cur := ref.(type) {
case string:
output = input.(map[string]interface{})[cur]
case int:
output = input.([]interface{})[cur]
}
}
return output
}
func NMap(input interface{}) (output …Run Code Online (Sandbox Code Playgroud) 在发生恐慌之前在堆或堆栈上分配的类型会发生什么?是否已调用析构函数以便取消分配类型?他们在记忆中徘徊等待被其他一些过程覆盖吗?或者它完全是另一回事?
我不知道,因为我是Rust和系统编程的新手.
我正在尝试从程序中创建的go例程中捕获崩溃/紧急情况,以便将其发送到崩溃错误报告服务器(例如Sentry / Raygun)
例如,
func main() {
go func() {
// Get this panic
panic("Go routine panic")
}()
}
Run Code Online (Sandbox Code Playgroud)
答案表明,一个goroutine无法从另一个goroutine的恐慌中恢复。
惯用的方式是什么?
我最近遇到的问题需要根据整数类型的位进行带边界的整数运算。
例如,使用i32整数进行add运算,这里有一段伪代码来表达这个想法:
sum = a + b
max(min(sum, 2147483647), -2147483648)
// if the sum is larger than 2147483647, then return 2147483647.
// if the sum is smaller than -2147483648, then return -2147483648.
Run Code Online (Sandbox Code Playgroud)
为了实现这一点,我天真地写了以下丑陋的代码:
sum = a + b
max(min(sum, 2147483647), -2147483648)
// if the sum is larger than 2147483647, then return 2147483647.
// if the sum is smaller than -2147483648, then return -2147483648.
Run Code Online (Sandbox Code Playgroud)
代码运行良好;但是我的六感告诉我使用类型转换是有问题的。因此,我尝试使用传统的恐慌(异常)处理来解决这个问题……但我坚持使用下面的代码(恐慌结果无法检测下溢或溢出):
fn i32_add_handling_by_casting(a: i32, b: i32) -> i32 {
let sum: …Run Code Online (Sandbox Code Playgroud) 此紧急恢复代码适用于命名的返回值。
func main() {
result, err := foo()
fmt.Println("result:", result)
if err != nil {
fmt.Println("err:", err)
}
}
func foo() (result int, err error) {
defer func() {
if e := recover(); e != nil {
result = -1
err = errors.New(e.(string))
}
}()
bar()
result = 100
err = nil
return
}
func bar() {
panic("panic happened")
}
Run Code Online (Sandbox Code Playgroud)
输出
result: -1
err: panic happened
Run Code Online (Sandbox Code Playgroud)
func main() {
result, err := foo() …Run Code Online (Sandbox Code Playgroud)