如何处理堆栈溢出?
我正在尝试修复 postscript 解释器中的错误处理,但我很难想出当其中一个堆栈已满时处理程序执行的方法。
我正在使用的 postscript 级处理程序过程是 Frank Merritt Braswell 中描述的“标准”过程,Inside Postscript。
/.error {
//$error exch /errorname exch put
//$error exch /command exch put
//$error /newerror true put
//$error /errorname get /VMerror ne {
//$error /ostackarray get null eq {
//$error /estackarray 250 array put
//$error /ostackarray 6000 array put
//$error /dstackarray 30 array put
} if
count
//$error /ostackarray get exch 0 exch getinterval astore
//$error exch /ostack exch put
//$error /dstack //$error /dstackarray get dictstack put
//$error /estack //$error /estackarray get execstack
dup length 2 sub 0 exch getinterval put
//$error /ostack get aload pop
} if
//$error /initializing get {
handleerror
} if
interrupt
} def
因此它需要操作数堆栈上的空间(用于 $error 字典和名称等内容) )和执行堆栈(对于过程体,如果执行的话)。那么如果任一堆栈溢出,这个空间应该来自哪里?
我尝试首先解决 execstackoverflow,因为使用 execstack 的运算符少于使用操作数堆栈的运算符。我定义了一个“缓冲区”大小
#define ERRDEPTH 5 /*space reserved on execstack for error handling*/
,所有“exec”运算符函数都将其添加到空间检查中。例如。这是exec
运算符。
void Aexec(state *st, object x) { (void)st;
if ((tes-es)+1+ERRDEPTH >= ESSIZE) error(st,execstackoverflow);
pushe(x);
}
然后解释器循环检查更小的大小(因此在尝试运行处理程序时不会触发更多错误)。
bool eval (state *st) {
...
/* room to work? */
if ((tes-es) + 2 /*+ ERRDEPTH*/ > ESSIZE) error(st,execstackoverflow);
...
但它不起作用(SEGFAULT),除非我在将 PS 处理程序推送(计划)到 execstack 之前清除 C 级错误处理程序中的一些空间。
...
if (e == execstackoverflow) { /* make some room! */
(void)pope(); (void)pope(); (void)pope(); (void)pope(); (void)pope();
(void)pope(); (void)pope(); (void)pope(); (void)pope(); (void)pope();
}
...
但现在我已经把孩子和洗澡水一起倒掉了!堆栈顶部的那些条目可能只是修复错误的关键信息,而我刚刚将它们扔进了深渊。
谁能建议一个更好的方法来解决这个问题?
I'm trying to fix up the error handling in my postscript interpreter, and I'm having difficulty coming up with ways for the handler to execute when one of the stacks is full.
The postscript-level handler procedure I'm using is the "standard" one described in Frank Merritt Braswell, Inside Postscript.
/.error {
//$error exch /errorname exch put
//$error exch /command exch put
//$error /newerror true put
//$error /errorname get /VMerror ne {
//$error /ostackarray get null eq {
//$error /estackarray 250 array put
//$error /ostackarray 6000 array put
//$error /dstackarray 30 array put
} if
count
//$error /ostackarray get exch 0 exch getinterval astore
//$error exch /ostack exch put
//$error /dstack //$error /dstackarray get dictstack put
//$error /estack //$error /estackarray get execstack
dup length 2 sub 0 exch getinterval put
//$error /ostack get aload pop
} if
//$error /initializing get {
handleerror
} if
interrupt
} def
So it needs space on the operand stack (for the $error dictionary and names and stuff) and execution stack (for the procedure bodies, if executed). So if either stack has overflowed, where is this space supposed to come from?
I attempted to tackle the execstackoverflow first, since fewer operators use the execstack than use the operand stack. I defined a "buffer" size
#define ERRDEPTH 5 /*space reserved on execstack for error handling*/
which all "exec" operator functions add to the space check. Eg. here's the exec
operator.
void Aexec(state *st, object x) { (void)st;
if ((tes-es)+1+ERRDEPTH >= ESSIZE) error(st,execstackoverflow);
pushe(x);
}
And then the interpreter loop checks for a much smaller size (so it doesn't trigger even more errors while trying to run the handler).
bool eval (state *st) {
...
/* room to work? */
if ((tes-es) + 2 /*+ ERRDEPTH*/ > ESSIZE) error(st,execstackoverflow);
...
But it doesn't work (SEGFAULT) unless I clear up some space in the C-level error handler, just before it pushes (schedules) the PS handler on the execstack.
...
if (e == execstackoverflow) { /* make some room! */
(void)pope(); (void)pope(); (void)pope(); (void)pope(); (void)pope();
(void)pope(); (void)pope(); (void)pope(); (void)pope(); (void)pope();
}
...
But now I've thrown the baby out with the bathwater! Those entries on the top of the stack might just be the crucial information for fixing the error, and I've just tossed them into the abyss.
Can anyone suggest a better way of going about this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果不太了解您的代码,我想创建一个可以自行扩展的错误堆栈将是解决方案。
Without knowing too much about your code, I would imagine creating an error stack that can expand itself would be the solution.