V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
helloworld12
V2EX  ›  问与答

golang slice 编译器 边界检测?

  •  
  •   helloworld12 · 2018-07-17 20:09:52 +08:00 · 1810 次点击
    这是一个创建于 2325 天前的主题,其中的信息可能已经有所发展或是发生改变。

    https://github.com/golang/go/blob/b59b42cee8c1ca209dafd952da872fd493b77405/src/encoding/binary/binary.go#L51-L54

    看里面的代码是说

    _ = b[1]
    

    可以用来,让编译器,进行边界检测

    但是:

    https://play.golang.org/p/SHG6bYjnw8_z

    这个是可以运行的,报错也是运行时报错?

    panic: runtime error: index out of range
    
    goroutine 1 [running]:
    main.main()
        /tmp/sandbox468585689/main.go:9 +0x20
    
    5 条回复    2018-07-18 11:57:17 +08:00
    lujjjh
        1
    lujjjh  
       2018-07-17 21:06:55 +08:00
    应该是为了减少运行时的 bounds check 的:

    uint16(b[0]) | uint16(b[1])<<8 会生成两条 bounds checks,但是如果先写一个 _ = b[1] 就可以减少一次( b[1] 检查过之后 b[0] 就不用检查了)。
    helloworld12
        2
    helloworld12  
    OP
       2018-07-18 00:34:56 +08:00
    @lujjjh 减少边界检测?不是直接取值吗? 边界检测有什么用, 不是超出范围就崩溃吗?
    lujjjh
        3
    lujjjh  
       2018-07-18 08:51:34 +08:00 via iPhone   ❤️ 2
    @helloworld12 之所以能抛出超出范围的 panic,就是因为边界检测的存在。编译器在编译的时候插入边界检测的指令,运行时进行边界检测。并不是像你理解的那样在编译期间做边界检测。

    所谓的 bounds check hint to compiler 是提示编译器这里可以优化成只插入一次边界检测,直接检测 b[1] 有没有越界。

    编译成汇编代码应该可以看出区别。
    helloworld12
        4
    helloworld12  
    OP
       2018-07-18 09:02:58 +08:00
    谢谢
    reus
        5
    reus  
       2018-07-18 11:57:17 +08:00
    不用看这个,有个 commit 会改进 bounds check elimination,这个会回滚的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1055 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 22:09 · PVG 06:09 · LAX 14:09 · JFK 17:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.