为什么切片长度大于容量会产生运行时错误?

发布于 2024-11-30 07:11:26 字数 923 浏览 3 评论 0原文

制作了一个容量小于长度的切片

package main

import "fmt"

func main() {

    type b []int
    var k = make([]b, 10, 5)
    fmt.Println(k[8])
}

,当尝试运行时会出现以下错误。

恐慌:运行时错误:makeslice:上限超出范围

runtime.panic+0x9e /go/src/pkg/runtime/proc.c:1060

runtime.panic(0x453b00, 0x30020390)runtime.panicstring+0x94 /go/src/pkg/runtime/runtime.c:116

runtime.panicstring(0x4afd6c, 0x40d80c)runtime.makeslice+0x70 /go/src/pkg/runtime/slice.c:24

runtime.makeslice(0x44302c, 0xa, 0x0, 0x5, 0x0, ...) main.main+0x45 C:/GOEXCE~1/basics/DATATY~1/slice.go:8

main.main()runtime.mainstart+0xf 386/asm.s:93 runtime.mainstart()runtime.goexit /go/src/pkg/runtime/proc.c:178

运行时.goexit()

----- 创建的 goroutine -----

_rt0_386+0xbf 386/asm.s:80

创建的 goroutine我的问题是容量可以小于长度吗?

如果“是”那么为什么会出现此错误?
如果“否”,那么为什么这是运行时错误,而不是编译时错误?

Made a slice where capacity is less than the length

package main

import "fmt"

func main() {

    type b []int
    var k = make([]b, 10, 5)
    fmt.Println(k[8])
}

This when tried to run gives following error.

panic: runtime error: makeslice: cap out of range

runtime.panic+0x9e /go/src/pkg/runtime/proc.c:1060

runtime.panic(0x453b00, 0x30020390) runtime.panicstring+0x94 /go/src/pkg/runtime/runtime.c:116

runtime.panicstring(0x4afd6c, 0x40d80c) runtime.makeslice+0x70 /go/src/pkg/runtime/slice.c:24

runtime.makeslice(0x44302c, 0xa, 0x0, 0x5, 0x0, ...) main.main+0x45 C:/GOEXCE~1/basics/DATATY~1/slice.go:8

main.main() runtime.mainstart+0xf 386/asm.s:93
runtime.mainstart() runtime.goexit /go/src/pkg/runtime/proc.c:178

runtime.goexit()

----- goroutine created by -----

_rt0_386+0xbf 386/asm.s:80

My question is can capacity be less than length?

If 'Yes' then why this error came?
And if 'No'then why this is a runtime error and why not a compile time?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

甜嗑 2024-12-07 07:11:26

不,容量不能小于长度。

切片是对数组的一部分的引用。切片的容量表示该后备数组的大小。如果它的长度大于它的容量,那么它使用什么内存?

以下不变量始终适用于切片 s(除非您做了不安全的事情):

0 <= len(s) <= cap(s)

您的代码会产生运行时错误而不是编译时错误,因为该错误始终无法静态检测到。在您的情况下可能是这样,但请考虑以下代码:

package main

import (
    "fmt"
    "rand"
)

func main() {
    k := make([]int, rand.Int(), rand.Int())
    fmt.Println(k)
}

传递给 make 的值直到运行时才能知道。

No, capacity cannot be less than length.

A slice is a reference to a part of an array. A slice's capacity represents the size of that backing array. If its length is greater than its capacity, then what memory is it using?

The following invariant always holds for a slice s (unless you've done something unsafe):

0 <= len(s) <= cap(s)

Your code produces a runtime error rather than a compile-time error because the error cannot always be detected statically. In your case it could be, but consider this code:

package main

import (
    "fmt"
    "rand"
)

func main() {
    k := make([]int, rand.Int(), rand.Int())
    fmt.Println(k)
}

The values passed to make cannot be known until runtime.

擦肩而过的背影 2024-12-07 07:11:26

阅读 Go 编程语言规范

长度和容量

切片的容量是切片中元素的数量
在底层数组中分配的空间。任何时候以下
关系成立:

0 <= len(s) <= cap(s)

Read the Go Programming Language Specification.

Length and capacity

The capacity of a slice is the number of elements for which there is
space allocated in the underlying array. At any time the following
relationship holds:

0 <= len(s) <= cap(s)
哆啦不做梦 2024-12-07 07:11:26

检查runtime/slice.go,

func makeslice(et *_type, len, cap int) unsafe.Pointer {
    mem, overflow := math.MulUintptr(et.size, uintptr(cap))
    if overflow || mem > maxAlloc || len < 0 || len > cap {
        // NOTE: Produce a 'len out of range' error instead of a
        // 'cap out of range' error when someone does make([]T, bignumber).
        // 'cap out of range' is true too, but since the cap is only being
        // supplied implicitly, saying len is clearer.
        // See golang.org/issue/4085.
        mem, overflow := math.MulUintptr(et.size, uintptr(len))
        if overflow || mem > maxAlloc || len < 0 {
            panicmakeslicelen()
        }
        panicmakeslicecap()
    }

    return mallocgc(mem, et, true)
}

它将检查len和cap,如果len<0或len>cap则给出恐慌。

check the runtime/slice.go

func makeslice(et *_type, len, cap int) unsafe.Pointer {
    mem, overflow := math.MulUintptr(et.size, uintptr(cap))
    if overflow || mem > maxAlloc || len < 0 || len > cap {
        // NOTE: Produce a 'len out of range' error instead of a
        // 'cap out of range' error when someone does make([]T, bignumber).
        // 'cap out of range' is true too, but since the cap is only being
        // supplied implicitly, saying len is clearer.
        // See golang.org/issue/4085.
        mem, overflow := math.MulUintptr(et.size, uintptr(len))
        if overflow || mem > maxAlloc || len < 0 {
            panicmakeslicelen()
        }
        panicmakeslicecap()
    }

    return mallocgc(mem, et, true)
}

it will check the len and the cap, and give a panic if len<0 or len>cap.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文