后记:最大数组大小?
postscript 数组有最大大小吗?
我编写了一个 PS 文档,其中包含一个数组,该数组在 Ghostview 中显示没有任何问题。
但是当这个数组中的项目数量增加时,ghostview 会引发以下异常:
ERROR: /stackoverflow in -file-
Operand stack:
--nostringval--
Execution stack:
%interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1 3 %oparray_pop 1 3 %oparray_pop 1 3 %oparray_pop 1 3 %oparray_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push
Dictionary stack:
--dict:1122/1686(ro)(G)-- --dict:0/20(G)-- --dict:122/200(L)--
Current allocation mode is local
Last OS error: 2
Current file position is 301163
ESP Ghostscript 815.02: Unrecoverable error, exit code 1
Is there a maximum size for a postscript array ?
I wrote a PS document containing containing an array that is displayed in ghostview without any problem.
But when the number of items in this array increases, ghostview raises the following exception:
ERROR: /stackoverflow in -file-
Operand stack:
--nostringval--
Execution stack:
%interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1 3 %oparray_pop 1 3 %oparray_pop 1 3 %oparray_pop 1 3 %oparray_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push
Dictionary stack:
--dict:1122/1686(ro)(G)-- --dict:0/20(G)-- --dict:122/200(L)--
Current allocation mode is local
Last OS error: 2
Current file position is 301163
ESP Ghostscript 815.02: Unrecoverable error, exit code 1
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
最大数组长度:65535。这也是最大字符串长度。但这似乎不是这里的问题。
Postscript Level 2 取消了堆栈大小的限制,因此它应该自动扩展到虚拟内存系统可以管理的任何大小。如果您收到 /stackoverflow 错误;您需要将您的口译员至少升级到 2 级 (1991) 标准。
编辑:也就是说,如果无法升级,可以通过多种方法来解决该问题。
由于堆栈是静态分配的,因此很可能会发生限制。如果您有权访问源代码,则只需增加大小并重新编译解释器即可。 PLRM 1ed 中引用的限制是 500。
另一个选择是改变您使用堆栈的方式(更难)。如果您无法使用
[]
或{}
构造 1000 个元素的数组,您仍然可以分配该数组 (1000 array
) 并用切片填充它正常构造 (dup dup 0 [ 0 1 .. 450 ] putinterval dup dup 450 [ 451 452 .. 900 ] putinterval dup dup 900 [ 901 902 .. 999 ] putinterval
)。请记住,标记也占用堆栈上的空间;某些操作符实际上是过程,它们需要堆栈空间来操作。编辑:如果数组确实很大,数组切片可能会遇到总内存限制;因为如果你没有不断增长的堆栈,你可能也没有垃圾收集。上述方法在 VM 中留下了 1000 个已使用且不可访问的数组元素。使用
packedarray
作为切片可能会在一定程度上解决这个问题。下一步是编写一个类似于 putinterval 和 PackedArray 混合的过程,可以将数据加载到数组中,而无需创建临时数组。由于我们正在更高级别重新实现低级别功能,因此运行速度可能会更慢。
这是第一刺。它提前读取(使用
currentfile token
)并将每个元素放入数组的后续位置。arrayfill
必须是源代码行上的最后一个单词(如image
),以便 currentfile 可以找到第一个元素(源代码行的其余部分位于内部扫描器缓冲区中)。There is a maximum array length: 65535. This is also the maximum string length. But that doesn't appear to be the problem here.
Postscript Level 2 removed the limit on stack size, so it should automatically expand to whatever size the virtual memory system can manage. If you're getting a /stackoverflow error; you need to upgrade your interpreter to at least the Level 2 (1991) standard.
Edit: That said, there are ways to work around the problem if upgrading isn't an option.
The limit most likely occurs because the stack is being statically allocated. If you have access to the source code, you can simply increase the size and recompile the interpreter. The limit quoted in the PLRM 1ed is 500.
Another option is to change the way you work with the stack (harder). If you cannot construct a 1000 element array using
[]
or{}
you can still allocate the array (1000 array
) and fill it with slices constructed normally (dup dup 0 [ 0 1 .. 450 ] putinterval dup dup 450 [ 451 452 .. 900 ] putinterval dup dup 900 [ 901 902 .. 999 ] putinterval
). Remember, marks take up space on the stack too; and certain operators are really procedures and they will need stack space to operate.Edit: If the arrays are truly huge, array slices may run you up against total memory limits; because if you don't have growing stacks, you probably don't have garbage collection either. The above method leaves 1000 arrays elements used and inaccessible in VM. Using
packedarray
for the slices might forstall this problem somewhat.The next step would be to write a procedure that works like a hybrid of putinterval and packedarray that can load data into an array without creating temporary arrays. This may run slower since we're reimplementing low-level functionality at a higher level.
Here's a first stab. It reads ahead (using
currentfile token
) and puts each element into subsequent positions of the array.arrayfill
must be the last word on the source line (likeimage
) so currentfile can find the first element (the remainder of the source line is in an internal scanner buffer).