当字符串设置为空时,字符串变量是否有可能具有中间状态?[关闭]

Is it possible that string variable has intermediate status when string is set as empty? [closed]

提问人:user3689723 提问时间:11/13/2023 最后编辑:Jonathan Halluser3689723 更新时间:11/13/2023 访问量:38

问:


这个问题是由错别字或无法再现的问题引起的。虽然类似的问题可能在这里是主题,但这个问题的解决方式不太可能帮助未来的读者。

6天前关闭。

我发现在多个 goroutine 中修改全局字符串字段时存在中间状态,根据下面的代码片段,有 3 个 goroutine 可以异步修改字符串字段,一个 goroutine 尝试打印这个全局字符串字段。

但是我得到了如下恐慌:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x45eacf]

goroutine 21 [running]:
fmt.(*buffer).writeString(...)
    /usr/local/go-faketime/src/fmt/print.go:108
fmt.(*fmt).padString(0x41d805?, {0x0, 0x3})
    /usr/local/go-faketime/src/fmt/format.go:110 +0x245
fmt.(*fmt).fmtS(0xc00003dd40?, {0x0?, 0x55e900?})
    /usr/local/go-faketime/src/fmt/format.go:359 +0x3f
fmt.(*pp).fmtString(0xedef741142500000?, {0x0?, 0xc0000b6010?}, 0x3ddb8?)
    /usr/local/go-faketime/src/fmt/print.go:497 +0xc5
fmt.(*pp).printArg(0xc0000aa270, {0x48b540?, 0xc0000ba940}, 0x73)
    /usr/local/go-faketime/src/fmt/print.go:741 +0x21e
fmt.(*pp).doPrintf(0xc0000aa270, {0x49c6b7, 0x9}, {0xc00009bfa8?, 0x1, 0x1})
    /usr/local/go-faketime/src/fmt/print.go:1077 +0x387
fmt.Fprintf({0x4b9e88, 0xc0000ac008}, {0x49c6b7, 0x9}, {0xc00003dfa8, 0x1, 0x1})
    /usr/local/go-faketime/src/fmt/print.go:224 +0x75
fmt.Printf(...)
    /usr/local/go-faketime/src/fmt/print.go:233
main.main.func4(0xc00009e230)
    /tmp/sandbox1267162307/prog.go:36 +0x6c
created by main.main
    /tmp/sandbox1267162307/prog.go:34 +0x155

看起来字符串字段处于中间状态(fmt.(*fmt).padString(0x41d805?, {0x0, 0x3})), 底层 bytes 数组更改为 0x0,但长度仍为 3,并引发了恐慌。

代码片段

// You can edit this code!
// Click here and start typing.
package main

import (
    "fmt"
    "time"
)

type BBB struct {
    appID string
}

func main() {
    b := &BBB{}
    go func(bb *BBB) {
        for {
            bb.appID = "bar"
        }
    }(b)

    go func(bb *BBB) {
        for {
            bb.appID = "foo"
        }
    }(b)

    go func(bb *BBB) {
        for {
            bb.appID = ""
        }
    }(b)

    go func(bb *BBB) {
        for {
            fmt.Printf("value:%s\n", bb.appID)
        }
    }(b)
    time.Sleep(100 * time.Second)
}

当 Go 中的字符串设置为空时,字符串变量是否有可能具有中间状态?

看起来这是正常情况,其他语言(例如 Java 和 Python)没有任何例外。

在 Go 中异步设置空字符串而引起恐慌的根本原因是什么?如果我们更改第三个 goroutine 以将非空值设置为此字符串变量,则恐慌就会消失。

恐慌

评论


答: 暂无答案