调试程序清华CAD二次开发LISP.ppt
第 6 章 调试程序,6.1 概述 语法正确的程序并不能保证正常运行,在运行时可能会产生错误的结果或者发生崩溃现象,这就需要调试。调试程序的步骤是:控制程序在指定的位置暂停;查看、分析有关变量的值;修改程序的源代码;继续或重新运行程序;如果程序不能正常运行,继续调试程序,直至程序正常运行。为了便于调试程序,Visual LISP提供了一些调试程序的工具,帮助用户迅速查找并改正程序中的错误。VisualLISP提供了监视窗口、检验窗口、符号服务对话框、中断和继续执行程序的模式、命令跟踪、跟踪堆栈、跟踪窗口等调试程序的工具。,通过图6-1示View下拉菜单和View工具栏可以调用监视窗口、检验窗口等调试工具。,检验窗口跟踪堆栈出错跟踪符号服务监视窗口自动匹配窗口断点窗口编译输出窗口VisualLISP控制台浏览图形数据库选择工具栏,图6-1 View下拉菜单,打开监视窗口匹配符号服务堆栈跟踪功能打开检测窗口激活控制台窗口确定活动窗口切换到AutoCAD图形窗口,通过图6-2所示Debug下拉菜单和Debug工具栏的选项可以设置程序暂停的模式和继续程序运行的方式。,只执行一步表达式求值。执行到下一个断点,如无断点,则执行一个完整的表达式求值。执行到下一个断点,如无断点,则执行一个最外层的表达式求值。继续执行程序结束当前程序。返回到控制台的上一层中断顶层读算写循环。结束所有当前活动的断点循环并返回到控制台的顶层读算写循环。添加监视回到最近一次监视窗口的环境设置/删除断点清除所有的断点回到源程序上的最近一次的断点跟踪命令立即暂停出错断开自动运行终止求值,图6-2 Debug下拉菜单,调试指示器按钮显示上一个断点添加监视设置或取消断点切换重置为顶层退出当前层继续执行跳出表达式下一个表达式下一层嵌套表达式,Debug工具栏,6.2 监视窗口 监视窗口用于监视变量、函数在程序运行过程中的结果。选择菜单DebugWatch Last Evaluation。将弹出图6-3所示的监视窗口。,图6-3 监视窗口,1.监视窗口的工具栏 监视窗口的工具栏有四个图像按钮,从左至右依次是:添加监视:将新的变量加入到监视窗口。清除变量:清除监视窗口内的所有的变量。排序:将监视窗口内的变量名按字母顺序排序。复制到跟踪/日志:将监视窗口的内容复制到跟踪窗口。如果打开了日志选项,监视窗口中的这些内容也将被复制到跟踪日志文件。,2.监视窗口的快捷菜单 选择监视列表中的某一项并单击鼠标右键,可显示图6-4所示监视窗口的快捷菜单。,调用检验功能,查看所选值。将所选变量的值复制到系统变量*obj*中。将所选变量值加上一个单引号前缀,打印到控制台窗口。对所选变量调用符号服务对话框。调用自动匹配选项对话框,用所选变量名作自动匹配参数。从监视窗口中删除所选变量。,图6-4监视窗口的快捷菜单,3.将变量加入到监视窗口有三种途径可以将新的变量加入到监视窗口。,(1)点取工具栏上的添加监视按钮,在随后弹出的图6-5所示的添加监视窗口内填入变量名,然后单击OK按钮。,图6-5添加监视窗口,(2)亮显要添加的变量名,然后点取工具栏上的添加监视按钮,随后弹出的图6-6所示的已填写了该变量名的添加监视窗口,然后单击OK按钮。(3)将光标移至将要添加的变量名,单击鼠标右键,在随后弹出的快捷菜单上选取Add Watch菜单项,将弹出已填写了该变量名的添加监视窗口,然后单击OK按钮。,4.监视变量的值 监视列表的每一行的格式是变量名=变量值,例如:A=1。如果程序尚未运行,变量的值是空的;随着程序的运行,在监视窗口可以看到变量的值也在不断变化。5.利用断点和监视窗口调试程序 假定在编辑器窗口已键入了图6-6所示的源程序。该程序的功能是根据用户输入的两个对角点绘制矩形。首先检查该程序是否存在语法错误。选择菜单ToolsText in Editor或单击按钮,在Build Output(输出)窗口显示;Check done.。说明该程序没有语法错误。选择菜单ToolsLoad Text in Editor或单击按钮,VisualLISP自动将控制切换到AutoCAD界面。当出现输入矩形的一个角点:的提示时,输入(0,0)点,该点是p1点的坐标;当出现输入矩形的对角点:的提示时,输入(100,100)点,该点是p2点的坐标。程序运行结束,只得到了矩形的两条边,显然,这不是预期的运行结果。,下面演示如何利用监视窗口调试程序。调试程序的步骤如下:(1)确定要监视的变量。选择菜单DebugAdd Watch或单击工具栏上的添加监视按钮,在随后弹出的添加监视窗口内填入变量名p1,然后单击OK按钮。用同样的操作监视变量P2、P3、P4。,图6-6监视P1、P2、P3、P4点的值,(2)从图6-7所示监视窗口可以看到:P1=0.0 0.0 0.0、p2=100.0 0.0、p3=100.0 100.0 0.0、P4=nil 100.0。说明P4点的X坐标是无定义的,而X坐标是(car pl)的返回值,检查(car pl),car是正确的,亮显pl,单击添加监视按钮,监视窗口内出现PL=nil,PL本不是该程序的变量,是p1的误写。(3)修改源程序代码,将pl改写为p1;重新加载、运行该程序;直到该程序可以正常运行,调试结束。,6.3 在不设置断点的情况下分步调试程序 分步调试就是将一个完整的程序分为若干步,逐步调试。每步可以是最内层的一个表达式,也可以是一个复杂的表达式,还可以是多个表达式。可以通过设置断点将程序分为若干段,也可以不用断点而是通过步长将程序分为若干步。结合下例程序介绍几种调试程序的方法。【例6-1】定义绘制矩形的命令,矩形的一个角点、宽、高和旋转角为交互输入的参数。程序的源代码如下:(defun c:rectr(/w h alf p1 p2 p3 p4)(setq p1(getpoint 输入矩形的一个角点:)w(getdist p1 输入矩形的宽:)h(getdist p1 输入矩形的高:)alf(getangle p1 输入矩形的旋转角:),(setq p2(polar p1 alf w)(setq p3(polar p2(+alf(*0.5 pi)h)(setq p4(polar p3(+alf pi)w)(command pline p1 p2 p3 p4 c)(princ)1.从第一个表达式开始,逐步调试程序(1)选择菜单FileOpen File或单击按钮,将例6-1所示源代码录入文本编辑窗口。选择菜单DebugAdd Watch或单击按钮,监视变量w、h、alf、p1、p2、p3、p4。选择菜单ToolsLoad Text in Editor或单击按钮,加载该程序。(2)通过菜单DebugStop Once,使之处于打开的状态。(3)单击按钮,切换到AutoCAD窗口,在AutoCAD的Command:提示下,键入rect3命令。,控制自动切换到VisualLISP文本编辑窗口,监视窗口内的变量值均为nil。此时光标停在(defun之前,整个程序被加亮显示。选取下拉菜单Debug的Step Into项、F8功能键或单击按钮,光标停在(setq p1之前,与之匹配的右括号之间被加亮显示。单击按钮,光标停在(getpoint 输入矩形的一个角点:)之前,并亮显该表达式。注意,指示按钮内的I在()之前。单击按钮,程序切换到AutoCAD窗口,出现输入矩形的一个角点:的提示,输入(100,80),程序切换到VisualLISP的文本编辑窗口。光标停在(getpoint 输入矩形的一个角点:)之后,仍然亮显该表达式。注意,指示按钮内的 I 在()之后。,单击按钮,光标停在(getdist p1 输入矩形的宽:)之前,并亮显该表达式。注意,指示按钮内的I回到()之前。监视窗口内的变量p1=100.0 80.0 0.0。重复类似的操作,在AutoCAD窗口输入矩形的宽度为200、高度为150,旋转角为30。在操作过程中指示按钮随时显示着光标相对于表达式的位置,监视窗口显示着这些变量的当前值(注意,alf的单位为弧度)。也说明单击按钮 只执行了一步表达式求值。当光标停在(setq p3(polar p2(+alf(*0.5 pi)h)之前时,单击按钮,整个程序被加亮显示,光标停在整个程序的结尾,再单击以上任一按钮,程序运行结束。切换到AutoCAD窗口,显示着刚才绘制的矩形。,假定程序的第5行误写为(getangl p1 输入矩形的旋转角:),仍旧用上述的方法调试该程序,当执行到输入矩形的旋转角:时,将出现提示;error:no function definition:GETANGL(没有GETANGL这个函数定义)。点取查找按钮,在随后弹出的 FIND 对话框的FindWhat编辑框输入查找内容为 GETANGL,单击 Find按钮,找到getangl并改正为getangle。重新调试程序,直至程序正常运行。,2.自动分步调试程序(1)自动分步调试程序的步骤 将例6-1源代码的文件装入文本编辑窗口。监视变量w、h、alf、p1、p2、p3、p4。加载该程序。选择菜单DebugAnimate。在AutoCAD的Command:提示下,键入rect3命令。Visua lLISP自动切换到文本编辑窗口。随着光标的位置、指示按钮 内I和()的变化,自动地执行每一个表达式的求值,监视窗口内的变量值也相应地改变。如果遇到了错误的函数调用,程序停止运行,并报告;error:no function definition:信息。找到并改正错误的函数。继续调试程序,直至程序正常运行。,(2)设置每步延迟的时间 选择菜单ToolsEnvironmant OptionsGeneral Options 弹出图6-7所示General Options对话框。单击该对话框的Diagnostic(诊断)卡,在Animation delay编辑框输入每步延迟的时间(以毫秒为单位),单击确定按钮即可。,图6-7诊断选项卡,6.4 断点循环 表达式是AutoLISP程序的基本单元,LISP的工作实际上是不断地对表达式进行读入、求值和输出操作,在LISP术语中,被称为读算写循环。如果不用调试工具而是正常地运行AutoLISP程序时,程序将处于顶层的读算写循环。如果在VisualLISP控制台窗口内对表达式求值时,也是处于顶层的读算写循环。如果程序在运行时被中断或挂起,VisualLISP将控制转交给控制台,就进入了断点循环(Break loop)。断点循环是一个单独的读算写循环,它嵌套在原有的读算写循环内。断点循环也可以被中断,这时将开始一个嵌套于该断点循环内的读算写循环。断点循环相对于顶层循环嵌套的层数称为该中断的层数。,进入断点循环时,VisualLISP将在控制台提示_$前加一个数字来指出所处循环的层数。例如,当首次进入程序的断点循环时,提示为_1_$。如果处于断点循环状态,就不能将控制切换到AutoCAD窗口。从断点循环退出,将恢复上一层循环。如果在该断点循环中修改了某变量的值,程序继续运行时将使用变量修改后的值。断点循环分为可继续断点循环和不可继续断点循环。,1.可继续的断点循环 可继续的断点循环是指可以在程序中断处,继续向下执行剩余的表达式。用以下方法进入可继续断点循环:(1)打开Stop Once模式,碰到带调试信息的表达式时。(2)遇到带Debug on Entry(进入时调试)标志的函数时。(3)遇到程序中设置的断点时。(4)单击暂停按钮进入断点循环时。(5)在前一个断点循环状态下,执行Step Into、Step Over或Step Out时。如果程序在某函数中被中断,可以访问被该函数声明的局部变量,甚至可以在控制台提示下用setq函数修改它们的值。,2.不可继续的断点循环 当程序出现错误导致崩溃时,如果设置了Break On Error选项,将激活一个不可继续的断点循环。此时可以访问出错环境中的所有变量,但不能继续执行程序或执行任何单步调试程序的命令。如果工具栏上的单步调试的按钮、或继续运行的按钮 处于可用状态,说明此时进入了可继续的断点循环。处于不可继续的断点循环时,选取Debug菜单的Reset to Top Level项或单击按钮,退出断点循环并跳转至控制台顶层循环;选取Debug菜单的Quit Current项或单击按钮,退出断点循环并返回到上一层循环。,6.5 利用断点调试程序 运行的程序遇到断点时,将产生一个中断。当程序中断时,可查看、分析变量的值,修改程序的源代码。利用断点可提高调试程序的效率。1.有关断点的操作(1)在程序中设置/删除断点 只能在VisualLISP的文本编辑器窗口内设置断点。断点应位于表达式的左、右括号上。设置断点的步骤如下:将光标移到需要程序暂停的位置。例如,需要在某表达式 之前暂停,则应将光标移至与表达式的左括号相邻的位置。,选择菜单DebugToggle Breakpoint、单击按钮 或按F9键。如果该位置没有断点,就加入一个断点,否则,删除该断点。单击鼠标右键在快捷菜单中选择Toggle Breakpoint项也可以设置或删除断点。如果光标不与括号相邻,Visual LISP暂时将光标移到后面最近的右括号处,并通过对话框询问用户是否在该处设置断点。选择菜单DebugClear All Breakpoints项,删除已设置的所有断点。,(2)改变断点的颜色 VisualLISP用高亮矩形显示每一个断点,默认情况下,活动的断点是红色的。选择菜单ToolsWindow AttributesConfigure Current,通过随后弹出的Window Attributes对话框内的WINDOW-TEXT下拉列表的:BPT-ACTIVE项可改变断点的颜色。(3)临时禁用断点 断点可以被临时禁用和恢复使用。禁用断点的步骤如下:将光标置于断点处并单击鼠标右键。从显示的快捷菜单上选择Breakpoints service项,将弹出图6-8所示断点服务对话框。,图6-8断点服务对话框,在断点服务对话框中单击Disable按钮可临时禁用该断点;若该断点已被禁用,图6-9所示断点服务对话框将出现Enable按钮,单击该按钮,所选断点将改变为可用状态。默认情况下,被禁用的断点显示为蓝色。用设置断点颜色的方法也可以改变被禁用断点的颜色。(4)浏览和编辑程序中的断点 选择菜单ViewBreakpoints Window将看到图6-9所示的断点对话框。,图6-9断点对话框,该断点窗口列出了所有编辑器窗口的断点。其中有程序6-1.lsp的3个断点、6-2.lsp的2个断点。每项包含断点的源文件名以及断点在源文件中的位置,位置是以0开始的西文字符数量,前面的+号表示该断点是活动的,-号表示该断点是被禁用的。单击该对话框的Delete all按钮可以删除所有的断点;亮显一项,单击Show按钮可显示该断点所在的源文件及其在源文件中的位置;单击Delete按钮可删除该断点;单击Edit按钮可打开图6-9所示的断点服务对话框,利用该对话框可以改变断点可用或禁用的状态。(5)断点的生命周期 可以在加载程序之前或之后设置断点。如果在加载程序之后设置断点,该断点只有在重新加载程序之后才有效。,2.在断点处继续运行程序 运行的程序遇到断点时,将产生一个中断,即断点循环。单击分布调试按钮、和 可继续运行程序。如果在复杂的表达式之内还有一些断点,单击按钮 和,首先在断点处暂停。此外还有以下控制程序继续运行的工具栏按钮、快捷键或Debug菜单的菜单项。Continue或Ctrl+F8:继续执行程序直至遇到下一个断点(如果有)或程序结束。Quit Current或Ctrl+Q:结束当前程序,返回到控制台的上一层断点循环。Reset to Top Level或Ctrl+R:结束当前程序,结束所有的断点循环。,3.利用断点调试程序实例【例6-2】定义绘制图6-10所示图形的命令,p0、d、b、t1、alf是交互输入的参数。,图6-10轴的键槽部位截面,程序源代码如下:(defun c:tuxing(/p0 alf d b t1 r l b1 sit p1 p2 p3 p4 p5)(setq p0(getpoint nEnter P0:)(setq d(getdist p0 nEnter d:),(setq b(getdist p0 nEnter b:)(setq tl(getdist p0 nEnter t1:);tl应改为t1(setq alf(getangle p0 nEnter alf:);断点1的位置(setq r(*0.5 d)bl(*0.5 b)(setq l(sqrt(-(*r r)(*b1 b1)(setq sit(tan b1 l);tan应改为atan(setq p1(polar p0(+alf sit)r)(setq p2(polar p0(+pi alf)r)(setq p3(polar p0(-alf sit)r)(setq p4(polar p3(+pi alf)(-(+r l)t1)(setq p5(polar p1(+alf pi)(-(+r l)t1)(command pline p1 a s p2 p3 l p4 p5 c),选择菜单FileOpen File将例6-2所示源代码的文件装入文本编辑窗口。选择菜单DebugAdd Watch或单击按钮,监视变量p0、d、b、t1、alf、r、l、b1、sit、p1、p2、p3、p4、p5。加载该程序,单击按钮,在AutoCAD的Command:提示下键入TUXING命令,程序停止运行,出现提示;error:bad argument type:numberp:nil(错误的参数类型,出现了无定义的参数)。将光标移至程序的第6行末尾,选择菜单DebugToggle Breakpoint、按功能键F9或单击按钮,在该处设置一个断点。,单击按钮,加载当前文本编辑窗口内的源程序。单击按钮,在Command:提示下键入TUXING命令,依次输入p0、d、b、t1、alf的值之后,回到文本编辑窗口。光标停留在断点1的位置,说明已执行了5个get表达式。浏览监视窗口,p0、d、b、alf已有具体的数值,而T1=nil,说明表达式(setq tl(getdist p0 nEnter t1:))有错误,仔细检查,发现误将t1写为tl。改正之后,单击按钮,单击按钮,在Command:提示下键入TUXING命令,依次输入p0等的数据,当程序停留在断点1的位置时,浏览监视窗口t1已有定义了。,单击继续按钮,程序停止运行,出现提示;error:no function definition:TAN(错误,没有定义函数:TAN),正确的函数应该是兰色的,找到黑色的函数名tan,改正为atan。将光标移至断点1处单击按钮,删除断点1。单击按钮,在Command:提示下键入TUXING命令,依次输入p0等的数据,程序正常结束,并得到图6-10所示图形。,图6-10,在此例中,在断点1暂停时,调试按钮从 到 都处于可用状态,因为此时处于可继续的断点循环。如果运行该程序前,选择菜单DebugBreak On Error,执行到tan函数时,因出现了无定义的函数而程序崩溃,但在该处产生了一个不可继续的断点循环。此时只有调试按钮 和是可用的。用户只能选择退到上一层断点循环还是退到顶层断点循环。如果在Command:提示下,键入TUXING命令,在要求用户输入数据时,按下Esc键,程序停止运行,此时也产生了一个不可继续的断点循环。,6.6 跟踪程序运行 跟踪程序运行的工具有命令跟踪、出错跟踪和跟踪堆栈。1.命令跟踪 如果打开命令跟踪模式,VisualLISP将在窗口跟踪有关AutoCAD命令的执行情况,以便监控程序是否在执行AutoCAD命令时出现了问题。例如,选择菜单DebugTrace Command,在Command:提示下,键入TUXING命令(假定程序能够正常运行),将在图6-11所示Trace窗口显示有关AutoCAD命令的执行情况的信息。,图6-11显示有关AutoCAD命令的执行情况的跟踪窗口,2.出错跟踪 出错跟踪是用Error Trace窗口录跟踪程序运行的结果。在跟踪窗口按鼠标右键,将弹出跟踪窗口的快捷菜单,见图6-13。下面以例6-3为例,介绍利用Error Trace窗口调试程序的方法。【例6-3】定义求解一元二次方程的函数一元二次方程的表达式为:如果 a=0,它不是一个二次方程;如果,方程有实数解,否则无解。方程的求根公式为:,程序内容如下:(defun roots(a b c/t1 t2 x1 x2);t1、t2、x1、x2是局部变量(if(/=a 0)(progn,(setq t1(-(*b b)(*4 a c);(if(=t1 0.0)(progn(setq t2(sqrt t1);(setq x1(/(+-b t2)(*2 a);此处有错(setq x2(/(-b t2)(*2 a);此处有错(print(list x1 x2)(print n根是复数.)(print n不是一个二次方程.)(princ);静默退出),选择菜单FileOpen File将例6-3所示源代码的文件装入文本编辑窗口。单击工具栏按钮。在Visual LISP Console(控制台)窗口的_$提示下键入(ROOTS 1 5 6)。显示了出错原因是错误的参数类型,见图6-12。,图6-12显示出运行错误的控制台窗口,选择菜单ViewError Trace或Ctrl+Shift+R。将出现图6-13所示的出错跟踪窗口。,图6-13出错跟踪窗口及其快捷菜单,出错跟踪窗口的第1行为:ERROR BREAK,表示因出错产生了一个中断。第2行为2+nil 1.0,记录了中断的原因是1.0与一个无定义的参数求和。亮显第2行,按鼠标右键,弹出图6-14所示的快捷菜单。选取快捷菜单的Call point source,与该错相关的表达式(+-b t2)被加亮显示。单击添加监视按钮,监视-b的值,在监视窗口看到-b的值为nil。原因是-b不是b的相反数,而是另一个尚未定义的变量。应改正为(-t2 b)。同样的过程可发现下一行的(-b t2)有相同性质的错误,应改为(-0 b t2)。运行改正后的程序,结果为(3.0 2.0)。,3.跟踪堆栈 跟踪堆栈保存着调用函数的历史记录。利用堆栈后进先出的特点,记录一系列的嵌套表达式的出口。当程序运行中断,如遇到断点,通过跟踪堆栈可以了解程序的运行状态。如果程序运行出现错误,导致程序崩溃,通过跟踪堆栈可以分析程序崩溃的原因。首先通过以下实例了解跟踪堆栈。将例6-4所示程序代码复制到VisualLISP文本编辑器窗口,在程序的第6行的右括号处设置断点。【例6-4】了解跟踪堆栈的结构 程序说明:stack-tracing是一个递归调用的,indexval是序号的初始值,maxval是序号的最大值。当indexval小于maxval时,打印indexval的值。st5是调用stack-tracing的主函数。,(defun stack-tracing(indexval maxval)(princ n递归函数实参=)(princ indexval)(if(indexval maxval)(stack-tracing(1+indexval)maxval)(princ n递归结束。);在这里设置一个断点)单击按钮,在控制台窗口键入(stack-tracing 1 5)运行该程序。当程序运行到断点暂停时,单击按钮,将弹出图6-14所示跟踪堆栈窗口。通过该跟踪堆栈窗口了解该程序的运行状态。,图6-14跟踪堆栈窗口,(1)跟踪堆栈窗口的结构 按钮 用于刷新跟踪堆栈窗口,按钮 用于将跟踪堆栈窗口中的内容复制到跟踪窗口或日志文件。每个堆栈元素占一行。每一行的前面都有一个用或括起的数字,数字表示该元素在跟踪堆栈的序号。,(2)堆栈元素的种类 堆栈元素可分为:函数调用框架、跟踪堆栈最顶端和最底端关键字的框架、顶端结构、Lambda结构和特殊结构五种类型。函数调用框架。表示单个函数调用。其格式如下:序号 函数名 参数.图6-14所示跟踪堆栈窗口的26行显示了调用stack-tracing函数时的函数调用框架。例如:2(STACK-TRACING 5 5)2表示它是堆栈元素列表的第二个元素,STACK-TRACING是函数名,其后的两个数字是传给该函数的实际参数值。跟踪堆栈最顶端和最底端的关键字框架。其格式如下::关键字框架类型 与程序状态相关的其他信息关键字框架代表VisualLISP环境中的一种特定的操作,关键字指明操作的类型。关键字框架只可能出现在堆栈的顶端或底端。,框架类型 发生的操作:ACAD-REQUEST 由 AutoCAD 命令行调用的函数。:DCL-ACTION 由AutoCAD要求执行对话框控件的动作。关键字:DCL-ACTION后的 两个字符串分别是控件名和控件值。如果出现的是一个数,则是对 话框回调函数的值。:INSPECT-EVAL 执行了检验功能。:INSPECT-VERBOSE 进入了图形检验器的入口函数。:TOP-COMMAND VisualLISP交互环境的动作。例如,加载文件或选取文本时直接运 行一个函数。:USER-INPUT 框架内的字符串是在控制台输入的。:WATCH-EVAL 执行了监视功能。,表6-1所示的关键字框架只能出现在堆栈的底端。,表6-1 底端关键字框架,图6-14所示跟踪堆栈窗口的第8行显示了本例堆栈底端关键字框架的信息。内容如下::USER-INPUT(stack-tracing 1 5)表示是用户在控制台输入了(stack-tracing 1 5)。,表6-2所示的关键字框架只能出现在堆栈顶端。,框架类型发生的操作:ACMD-CALLBACK调用了已注册的AutoCAD命令。:AFTER-EXP程序正处于调试中断模式,且刚用Step Into或Step Over选项步出某表达式。:ARQ-SUBR-CALLBACK表示从AutoCAD窗口调用标准的VisualLISP定义的函数。:AXVLO-IO-CALLBACK:DWF或:DWG在DWG或DWF文件保存或恢复VLA对象。:BEFORE-EXP进入函数时用调试器中断了程序。当用户用Step Into 或Step Over命令步入某表达式时会出现该消息。:BREAK-POINT用户指定的断点。:ENTRY-NAMESPACE一个独立VLX命名空间上下文中的调用。:ERROR-BREAK一般的运行时错误。单击鼠标右键,选择菜单中的Show Message菜单项,可以查看更详细的出错信息。:FUNCTION-ENTRY在进入函数时调试器中断了程序。该消息后的下一个堆栈元素包含了引发中断的函数的调用框架。:KBD-BREAK按下了Pause键,程序被挂起。:PROTECT-ASSIGN为受保护的符号赋值。单击鼠标右键,选择菜单中的Show Message菜单项,查看变量名、变量当前值和试图赋给该变量的新值。也可以选择Inspect项,查看包含该符号的表,以及跟随在:PROTECT-ASSIGN 之后的新值。:REACTOR-CALLBACK调用了反应器。:READ-ERROR在读操作时发生的错误。单击鼠标右键,选择菜单中的Show Message菜单项,可获得更详细的出错信息。:SYNTAX-ERROR遇到了AutoLISP语法错误。,表6-2顶端关键字框架表6-2顶端关键字框架,图6-14所示跟踪堆栈窗口的第1行显示了本例堆栈顶端关键字框架的信息。内容如下::BREAK-POINT表示程序运行的最后一个操作是遇到用户设置的断点。顶端结构。它说明相应动作是由顶层控制台窗口中输入的表达式引起,或在VisualLISP文本编辑器窗口中加载文件或所选文本时触发的函数调用引起的。Lambda 结构。当程序调用lambda函数时,VisualLISP 会在堆栈中放入该结构。特殊结构。调用foreach和repeat函数时,VisualLISP 在堆栈中加入该结构,该结构中不显示函数的参数,其格式如下:FOREACH或REPEAT lFOREACH 框架表示对foreach函数的调用。例如,对以下表达式求值:(foreach n(a b c)(print n);在表达式开始处设置断点单步运行该表达式,当执行到(print n)时,选择菜单ViewTrace stack项,将弹出图6-15所示跟踪堆栈窗口。,图6-15调用foreach函数时的跟踪堆栈窗口,该窗口的第一行为:AFTER-EXP,其中1是该元素的序号,从表6-2所示顶端关键字框架表中可看到,AFTER-EXP表示程序正处于调试中断模式,且刚用Step Into或Step Over选项步出某表达式。该窗口的第二行为2FOREACH,其中2是该元素的序号,FOREACH是该函数的形式。lREPEAT 框架表示对repeat 函数的调用。例如,对以下表达式求值:(setq i 0)(repeat 10(princ(1+i),单步运行该表达式,执行到(1+i)时,选择菜单ViewTrace stack项,将弹出图6-16所示跟踪堆栈窗口。,图6-16调用repeat函数时的跟踪堆栈窗口,if、cond和setq 等函数并不出现在跟踪堆栈里,因为在源文件的VisualLISP文本编辑器窗口可以看到它们被调用的位置。,根据图6-14所示跟踪堆栈窗口,可以看出stack-tracing从调用到中断的过程如下:第8行::USER-INPUT(stack-tracing 1 5)用户在控制台输入了(stack-tracing 1 5),调用了该函数。,图6-14跟踪堆栈窗口,第7行:7(USUBR034086e0-top-)该函数的地址。第6行:6(stack-tracing 1 5)indexval等于1,maxval等于5调用该函数。第5行:5(stack-tracing 2 5)indexval等于2,maxval等于5调用该函数。第4行:4(stack-tracing 3 5)indexval等于3,maxval等于5调用该函数。第3行:3(stack-tracing 4 5)indexval等于4,maxval等于5调用该函数。第2行:2(stack-tracing 5 5)indexval等于5,maxval等于5调用该函数。第1行::BREAK-POINT 遇到用户设置的断点暂停,6.7 修改变量和函数的特性1.符号服务对话框的功能 符号可以是变量或函数名。通过符号服务对话框可以查看或修改变量的当前值,可以设置变量或函数的一些特性。2.符号服务对话框的组成,图6-17符号服务对话框,图6-17所示为符号服务对话框,它由工具栏、符号名、符号值和符号标志四部分组成。(1)工具栏:工具栏提供了对符号操作的工具。它包括以下四个图像按钮:将当前符号加入到监视窗口。检验该符号的值。如果该符号是用户定义的函数名,则打开包含该函数定义的文本编辑器窗口,并亮显该函数的定义。如果该符号是一个内部函数名,则显示VisualLISP帮助文件中的相关信息。(2)Name编辑框:显示被操作的符号名。(3)Value编辑框:显示符号值或它最初的子串。,(4)Flags组:该组有以下四个切换开关,其特性如下:Trace切换开关:对设置为Trace标志的函数,在Trace窗口显示对其跟踪的信息。该标志只对作为函数名的符号有效。Protect Assign切换开关:该标志的符号受到保护。程序运行时如果对受到保护的符号赋值,将产生询问信息。受到保护的符号在文本编辑窗口呈蓝色显示。在默认情况下,所有AutoLISP内置函数的函数名都受到保护。例如,符号pi、setq就是受到保护的符号。Debug on Entry切换开关:如果设置了该标志,不管是否加载了该函数的调试信息,在每次调用该函数时都会产生中断。该标志只对用户定义的函数起作用。Export to AutoCAD切换开关:如果设置了该标志,那么与该符号相关联的函数会被定义为外部函数,这样的函数可以被ObjectARX应用程序调用。,3.打开符号服务对话框有两种打开符号服务对话框的途径(1)在程序源代码或控制台窗口中亮显所需符号名,然后选择菜单ViewSymbol Service,或单击Debug工具栏上的按钮。(2)先选择上述菜单或图像按钮,在随后弹出的图6-18所示的符号服务对话框内输入符号名或在下拉列表中选取符号名,若光标附近有符号名,则该符号名作为新符号名的缺省输入。单击OK按钮即可打开图6-17所示的符号服务对话框。,图6-18输入符号名之前的符号服务对话框,4.修改变量的值假定某程序有以下两行代码:(setq a 1);此处设置一个断点(princ a)当程序遇到断点暂停时,亮显变量a,单击按钮,在随后弹出的符号服务对话框的Value编辑框里显示了变量a的当前值为1。将该值修改为2,点取OK按钮。单击按钮,将在控制台将打印出变量a的结果为2。说明完成了对变量a的修改。如果是可继续的断点循环,利用符号服务对话框的这一功能,可以直接改变变量的值继续运行程序。,5.设置符号的特性 假定有以下表达式:(setq a(+b c));可以是任一含有变量b的表达式 亮显变量b,单击按钮,将随后弹出的服务对话框的Flags组的Protect Assign切换开关设置为开,单击OK按钮。变量b呈兰色显示,说明它已成为受保护符号。在随后的表达式中,如果直接或间接改变b的值,将出现图6-19所示的提示。用是相应,程序在此处暂停;用否相应,符号b可以被改变。,图6-19 询问是否为受保护符号赋值的对话框,解除符号保护状态的操作与此类似,只是将Protect Assign切换开关设置为关闭状态。,6.设置函数在被调用时处于暂停的状态 将例6-4所示程序代码复制到VisualLISP文本编辑器窗口,删除程序中的断点,亮显函数名stack-tracing,点取按钮,将随后弹出的服务对话框的Flags组的Debug on Entry 切换开关切换开关设置为开,点取OK按钮。然后运行该程序。当程序运行遇到对stack-tracing函数的调用时,不管事前是否在函数内设置了断点,当程序运行到该函数时,自动处于暂停的状态。此时可利用各种调试程序的工具查看、检验或分析变量的结果。,6.8 检验窗口1.检验窗口的功能 检验窗口的功能是浏览或检验查数字、字符串、变量、表、AutoCAD的图形元素、AutoCAD的选择集等AutoLISP和AutoCAD对象。使用检验窗口还可以浏览复杂对象的数据结构和浏览ActiveX对象。2.检验窗口的结构,标题栏对象行元素表,图6-20检验窗口的结构,验窗口的样式见图6-20。窗口的内容与被操作对象的种类相关。所有的检验窗口都有一个标题栏、对象行和元素表(该表可能为空)。,(1)标题栏:对话框的标题,同时显示所了解对象的类型。(2)对象行:对象名或对象值。(3)元素表:组成该对象的成员。对象种类不同,元素表的大小和内容就有所不同。元素表的每一项(行)都分为名称和内容两部分。名称用括号括起,方括号 说明可以通过与该项关联的快捷菜单的修改选项修改该项;而花括号 说明用户不能修改该项。对象栏和元素表都有与自己的关联快捷菜单。3.打开检验窗口的步骤 选中某AutoLISP对象名(例如某变量)从 VisualLISP选择菜单ViewInspect,或单击Debug工具栏按钮。也可以通过快捷菜单选择Inspect项,或者选择Symbol Service等窗口工具栏的按钮。如果在调用检验窗口之前没有选中对象,VisualLISP将显示图6-21所示对话框,提示用户输入要检验的对象。,图6-21输入检验对象的对话框,VisualLIS