加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

是否有必要进行早期检查以确保Golang中写入的安全性?

发布时间:2020-12-16 19:03:35 所属栏目:大数据 来源:网络整理
导读:如果你看一下“encoding / binary”包: func (littleEndian) Uint64(b []byte) uint64 { _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 return uint64(b[0]) | uint64(b[1])8 | uint64(b[2])16 | uint64(b[3])24 | uint64(b[4])3
如果你看一下“encoding / binary”包:
func (littleEndian) Uint64(b []byte) uint64 {
    _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
    return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
        uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
}

func (littleEndian) PutUint64(b []byte,v uint64) {
    _ = b[7] // early bounds check to guarantee safety of writes below
    b[0] = byte(v)
    b[1] = byte(v >> 8)
    b[2] = byte(v >> 16)
    b[3] = byte(v >> 24)
    b[4] = byte(v >> 32)
    b[5] = byte(v >> 40)
    b[6] = byte(v >> 48)
    b[7] = byte(v >> 56)
}

你会看见:

_ = b[7] // early bounds check to guarantee safety of writes below

现在考虑这个示例代码A(请参阅注释):

package main

import "fmt"

func main() {
    b := []byte{0,1,2,3,4,5,6}
    var v uint64 = 0x0807060504030201

    b[0] = byte(v)
    b[1] = byte(v >> 8)
    b[2] = byte(v >> 16)
    b[3] = byte(v >> 24)
    b[4] = byte(v >> 32)
    b[5] = byte(v >> 40)
    b[6] = byte(v >> 48)
    b[7] = byte(v >> 56) // panic: runtime error: index out of range

    fmt.Println(b)
}

这个示例代码B(见注释):

package main

import "fmt"

func main() {
    b := []byte{0,6}
    var v uint64 = 0x0807060504030201

    b[7] = byte(v >> 56) // panic: runtime error: index out of range
    b[6] = byte(v >> 48)
    b[5] = byte(v >> 40)
    b[4] = byte(v >> 32)
    b[3] = byte(v >> 24)
    b[2] = byte(v >> 16)
    b[1] = byte(v >> 8)
    b[0] = byte(v)

    fmt.Println(b)
}

示例代码C:

package main

import "fmt"

func main() {
    b := []byte{0,6}
    var v uint64 = 0x0807060504030201

    _ = b[7] // early bounds check to guarantee safety of writes below

    b[0] = byte(v)
    b[1] = byte(v >> 8)
    b[2] = byte(v >> 16)
    b[3] = byte(v >> 24)
    b[4] = byte(v >> 32)
    b[5] = byte(v >> 40)
    b[6] = byte(v >> 48)
    b[7] = byte(v >> 56)

    fmt.Println(b)
}

所以我有两个问题:
Q1:是否有必要进行早期检查以确保Golang的写入安全性?
Q2:对于早期检查,保证写入的安全性,样本代码更简洁,性能更优化(速度),样本代码A,B,C或……?

A2:我觉得B:因为它简洁而且做早期检查,不是吗?

Q1: is it necessary to early bounds check to guarantee safety of writes in Golang?

这里的答案是“是和否”.通常,“不”,您通常不必在Go中插入边界检查,因为编译器会为您插入它们(这就是为什么当您尝试访问超出切片长度的内存位置时,示例会出现紧急情况).但是,如果您正在执行多次写入,例如给出的示例,“是”,则需要插入早期边界检查,例如提供的示例,以确保您没有只有部分写入成功,处于错误状态(或者像在示例B中那样重构,以便第一次写入到最大的数组,确保在任何写入成功之前发生恐慌).

然而,这不是一个“问题”,因为它是一个通用的bug类.如果您不以任何语言进行边界检查(或者不以最高索引开始,如果它是一种强制执行边界检查自己的语言,如Go),则写入不安全.它也在很大程度上取决于情况;在您发布的标准库的示例中,必须进行用户边界检查.但是,在您发布的第二个示例中,不需要进行用户边界检查,因为代码可以像B一样编写,其中编译器在第一行插入边界检查.

Q2: for early bounds check to guarantee safety of writes which Sample Code is more concise and performance optimized (speed),sample code A,C or … ?

A2: I think B : because it is concise and do early bounds check,isn’t it?

你是对的.在B中,编译器将在第一次写入时插入边界检查,以保护其余写入.因为您使用常量(7,6,… 0)索引切片,所以编译器可以从其余写入中删除边界检查,因为它可以保证它们是安全的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读