在对用户自定义类型数组进行切片和拷贝之后,array.push() 会导致“下标越界”

编程语言 2026-07-11

在移除数组前缀时,我遇到了一个运行时错误。

我想要做的事:

我有一个检测器自定义类型(Detector UDT),它在一个数组中维护着Thing对象的历史。在某些情况下,我需要移除这个数组的前缀。我通过取一个表示该数组后缀的切片来实现,并用该切片的副本替换原数组。

问题:

在完成这次切片和拷贝操作后的下一根bar上,对新数组执行 array.push() 时,会抛出一个运行时错误:索引越界。有趣的是,只有在脚本执行流程后续的某个switch语句读取测试结果时,错误才会触发。移除switch语句后,错误就消失了。我无法解释这种交互。

重现:

//@version=6
indicator("Repro")

type Thing
    int pos = -1
    bool output = false

type Detector
    array<Thing> things = na

method detect(Detector self, Thing t) =>
    if na(self.things)
        self.things := array.new<Thing>()

    self.things.push(t)
    prefix = self.things.slice(0, t.pos + 1)

    if t.output
        suffix = self.things.slice(t.pos + 1, self.things.size())
        self.things := suffix.copy()

var Detector detector = Detector.new()

thing = switch bar_index
    0 => Thing.new(pos=-1, output=false)
    1 => Thing.new(pos=0, output=true)
    2 => Thing.new(pos=0, output=true)
    3 => Thing.new(pos=-1, output=false)

run_bar() =>
    detector.detect(thing)
    true

bool passed = true
passed := passed and run_bar()

result_colour = switch
    passed => color.green
    => color.red

bgcolor(result_colour)

期望行为

push() 在Bar 3上的调用应当成功。

实际行为

脚本在Bar 3上失败,出现如下运行时错误:

Error on bar 3: In 'array.insert()' function. Index 2 is out of bounds, array size is 2.
at detect():17
at run_bar():33
at #main():37

感谢关注。希望我们能够为这个问题找到线索。

解决方案

问题的核心在于,你试图通过把 self.things 变量重新赋值为一个新的实例(suffix.copy())来“清理”数组。

在Pine Script中,当你使用 var Detector detector 时,对象会持续存在。然而,当你执行 self.things := suffix.copy() 时,你正在破坏Pine Script内部跟踪的原始数组引用。与 switch 语句相关的这种奇怪交互,是因为 switch 语句(以及其他流程控制结构)迫使编译器为变量的状态创建保存点。

如果编译器检测到数组的大小应基于上一次执行,但由于 copy() 导致引用发生变化,内部的插入指针就会失效。

以下是修正后的代码:

//@version=6
indicator("Reprp")

type Thing
    int pos = -1
    bool output = false

type Detector
    array<Thing> things = na

method detect(Detector self, Thing t) =>
    if na(self.things)
        self.things := array.new<Thing>()

    self.things.push(t)

    if t.output

        int items_to_remove = t.pos + 1


        if items_to_remove > 0 and self.things.size() >= items_to_remove
            for i = 1 to items_to_remove
                self.things.shift() 

var Detector detector = Detector.new()

thing = switch bar_index
    0 => Thing.new(pos=-1, output=false)
    1 => Thing.new(pos=0, output=true)
    2 => Thing.new(pos=0, output=true)
    3 => Thing.new(pos=-1, output=false)
    => na

run_bar() =>
    if not na(thing)
        detector.detect(thing)
    true

bool passed = true
passed := passed and run_bar()

result_colour = switch
    passed => color.green
    => color.red

bgcolor(result_colour)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章