Постскриптум: максимальный размер массива? - PullRequest
1 голос
/ 29 сентября 2011

Существует ли максимальный размер для массива 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

1 Ответ

3 голосов
/ 29 сентября 2011

Максимальная длина массива: 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). Помните, что метки также занимают место в стеке; и некоторые операторы на самом деле являются процедурами, и им потребуется пространство стека для работы.

Редактировать: Если массивы действительно огромные, срезы массивов могут привести вас к ограничению общего объема памяти; потому что если у вас нет растущих стеков, у вас, вероятно, также нет сборки мусора. Вышеупомянутый метод оставляет 1000 элементов массива, используемых и недоступных в VM. Использование packedarray для срезов может несколько решить эту проблему.

Следующим шагом будет написание процедуры, которая работает как гибрид putinterval и packararray, который может загружать данные в массив без создания временных массивов. Это может работать медленнее, поскольку мы реализуем низкоуровневую функциональность на более высоком уровне.

Вот первый удар. Он читает вперед (используя currentfile token) и помещает каждый элемент в последующие позиции массива. arrayfill должно быть последним словом в строке источника (например, image), чтобы currentfile мог найти первый элемент (остаток строки источника находится во внутреннем буфере сканера).

% array index count  arrayfill(NL)  array
% elem_0 elem_1 ..
% elem_count-1
/arrayfill { %a i c
    1 index add 1 sub %a ini fin
    1 exch { %a i
        2 copy %a i a i
        currentfile token pop %a i a i el
        put %a i
        pop %a
    } for
} def

%example
5 array 0 5 arrayfill
(0) (1) (2) (3) (4)
{=} forall
...