EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
MATLAB程序调试基本方法分享1 G* b6 D0 {1 C# f9 O Y! q/ I4 `4 E
前言, z4 m" ]! U2 M0 n/ x: d$ h7 u
本文主要是对MATLAB程序调试中的一般方法进行总结,也是自己学习的记录。全文大致分为三个段落:
- y1 y( ^. f% _2 M7 p0 {+ m8 w/ v! P: ]% a5 ^; u0 h/ t
1)代码内调试;
/ i& F: ?/ `& u7 I6 H
1 G$ ~1 w3 z! h: m/ p2 i 2)断点调试方法;
1 T Y4 f6 m. Y( o. ^( ~# j4 Y* I* I I+ W$ V5 E
3)指令调试方法;1 K/ ~: j. i3 ?. x, F: G
# l5 `. w- ^) Q2 o5 n$ }# L
本文主要为个人学习总结,并借鉴了前人的经验,相应链接在最后一并附上。
' |; b$ Q I5 x! C' l H( ]
" Z8 y" A ?* X0 Z5 W$ ?1 D& ]0 P. r M# v
一、代码内调试
! S/ Q; J2 G1 ^; J7 n/ s" \ A-打印变量
8 p( `' ?8 f) D- z=hilbert(testdata'); % 希尔伯特变换
- a=abs(z) % 包络线
- fnor=instfreq(z); % 瞬时频率' Q' S: C4 g9 @/ Z9 n" n
) c4 k: m3 Q% g
$ P5 Y& v/ d' d1 E* z$ w
上面的代码,如果希望检查a是否正常:去掉末尾的分号;,即可在Command Window查看到对应的输出信息,特别是当变量出现在function时,如果不输出,则在Workspace中无法直接查看,此时该操作较方便。; q' B7 }& j$ g; C: i& z
B-局部执行
2 s0 s3 P' I2 \2 a5 Q) ~- z=hilbert(testdata'); % 希尔伯特变换
- a=abs(z); % 包络线
- fnor=instfreq(z); % 瞬时频率
2 u0 _5 o! x5 k' g
% y# N, }- t3 P9 Q+ z5 O' q) Z4 f. l7 M% i2 a: j
如果希望对某一部分代码,进行调试,则完全没有必要每次都从头运行,这时局部执行较方便。仍是这段代码,如果希望仅仅执行高亮部分,则箭头选中并按F9,此时程序仅仅运行高亮部分,可利用这个方法调试局部代码。7 x0 k2 J/ k% P* X( w k8 p& G
C-配合绘图(该操作可以配合以下各类方法使用). F$ ~3 n X" D& X
图形比数据更易于观察,在调试过程中打开Workspace中的变量(快捷键:Crtl + D),然后选择plot,即可根据需求对数据进行绘图,便于观察特性:
9 s4 Y( h( i6 g. `# a- g
% h3 P; P2 Y4 P- j+ ]0 G例如选择需要观察的数据,分别选择bar以及suRF指令,即可绘制对应图形: ) b# F6 {1 P: b0 h
" g; B5 V8 a9 j8 o% p: ?, p
是不是也算方便?
7 g. z2 p- @0 o; t8 J$ @$ C. _9 t/ m5 _6 {; ~" `
6 [$ v. c4 \, W& ] r2 H' M二、断点调试方法 & j5 i- p" T! t! t: e8 s
调试代码最经典的就是利用设置断点的方法,此处给出对应快捷键: - @" V; K4 C$ h1 i* ]. p& |5 d
- F12:设置/取消 断点
- F10:单步执行
- F11:单步执行,且碰到function跳入函数内执行,F10则不会跳入,这是二者的明显区别
- Shift + F11:跳入function之后,通过该指令推出function
- F5:执行相邻两次断点见的所有指令,如:断点在for循环中,则F5一次,循环执行一次
- Shift + F5:退出断点调试8 ?/ E' O) c7 U! t8 d
' N% A) S0 [+ \: T9 v + o: k7 g: T1 F3 B6 {$ `: T; s
三、指令调试方法 , u! }9 M$ b. z6 G7 [9 o( }
A-keyboard + (return). Q1 |4 }) O/ \
经常碰到一些情况,如:矩阵相乘A*B时(假设A已知,B需要运算得出),矩阵B的size难以确定,是用A*B还是A'*B难以确定,可不可以先计算B,运算完之后观察B的特性,再确定用A还是A‘?keyboard可以解决这个问题。 keyboard顾名思义,就是键盘的意思,即:把控制权交给键盘。执行程序的过程中,把控制权交给键盘,如何再重新返回程序呢?因此: keyboard 与 return 通常联合使用。如执行: - max_eig = max( eig(G'*pinv(F)*G) ); %此处难以确定,还是max_eig = max( eig(G*pinv(F)*G') )
- P_tmp = real(m+1 - max_eig);
; b) D9 X. N( z5 I+ g Z $ v& x# Q$ q* ? y
7 @- O# O$ x6 I/ i, d$ s- b
但难以确定G还是G’,利用keyboard则可以修改为: - keyboard
- P_tmp = real(m+1 - max_eig);# L7 j k: o$ E2 H' D( E7 K5 E Y
3 G& q. e7 T0 N. G" P0 U7 w
+ X8 z! m! M( U3 ` G+ K( x* k& `+ n# k: D K, L. d
在进入K>> 之后,此时已经可以观察F、G的size,因此在Command Windows输入: - max_eig = max( eig(G'*pinv(F)*G) );
- return;
( v" _! \: k! T8 k; T5 Z2 Q3 c. v
/ Y& d; `+ A* c" ^) m+ f9 A
; D4 Y% c" _1 B/ ?; S$ O' F即可保证程序顺利执行。 B- try + (catch) + end 我们知道,matlab的代码是按行执行的,如果碰到错误行,则程序中断。try..catch可以使得可能出错的代码不影响后面代码的继续执行,也可以检查,排查,解决程序的一些错误,增强代码的鲁棒性和可靠性。 - try ... end
9 c$ n# A) s/ p i3 h try...end用于尝试运行一段也许可能出错的代码,比如:- m = rand(3,4);
- n = magic(5);
- try
- a = m*n;
- disp(a)
- end
- disp(m)
, l0 i* E; t) Z 4 D! ~5 M9 C4 s" J+ h
" {9 }* k; v k/ Z1 v; T9 B+ }这段代码里面,a = m*n运行会出错,不满足矩阵乘法的原则。所以,a = m*n和disp(a)不执行,但后面的disp(m)亦然会执行。
: ~, a7 E& ]8 c- try...catch...end. d* u& d0 P9 w. o: f1 w
try...catch...end用于检查错误,如 - m = rand(3,4);
- n = magic(5);
- try
- a = m*n;
- disp(a)
- catch
- disp(size(m))
- disp(size(n))
- end
- disp(m). m* P. c9 R% K
9 }# ?' b% X1 A: J. Q
1 p4 b* J/ w" H5 m: D' K3 S这里面,当程序碰到 a = m*n;错误后,就会跳转到catch里面的语句,继续执行,有点类似于if...else...end。 C-dbstop - dbstop if error7 Z- d7 c/ _) u' q/ X( [/ g
在程序执行前输入: - dbstop if error
- %================以下为main部分=================
- ....%略4 }7 ~+ \" p5 D+ I
& d. a7 W, J% S- s# W5 V; g7 c
" d: x# Q# ]# W; T' ]. s 如果运行出现错误,matlab会自动停在出错的那行,并且保存所有相关变量。真心好用。 - dbstop in file# p! L1 {8 \. M; F' r4 L% R7 V
在.m文件中,插入dbstop in file指令,如下面这段程序,我们在其中加入了dbstop in VMD,其中VMD是一个function: - load './data/Gdpyear.mat'
- data=data-mean(data);%去均值,即数据中心化
- dbstop in VMD
- t=linspace(1992.0,2016.5,length(data)); %设定x轴
- for st=1:9
- K=st+1;
- [u, u_hat, omega] = VMD(data, length(data), 0, K, 0, 1, 1e-5);
- u=flipud(u);
# p* R- R3 u$ `5 x: \ ( v5 h _+ {( s% j J4 z
/ {. y/ d0 w5 f( y) O; y
效果如下:
2 F* H- a' [" [% f Q
即设置断点并运行至VMD程序内部,此时通过F10/F11/Shift F11等断点操作中的快捷键,即可进行调试,Command Windows输入dbquit即可退出。 - dbstop in file at location if expression3 j$ A' @4 k6 f6 T4 x$ N
比如有myprogram.m, 如下: - clear all;
- close all
- clc;
- x = ones(1,10);
- for n = 1:10
- x(n) = x(n) + 1;
- end4 \1 F; w" M) h: l
C7 u. M3 o4 @: r' X g
& x3 {7 D+ M5 w0 O( i* J \2 \设置一个断点在 n >= 4时(对应程序位置为第6行),然后再运行程序: - dbstop in myprogram at 6 if n>=4;
- myprogram;7 z9 x2 o; Z- J7 `* L- Y+ x
+ }2 ^+ u! u& Z9 Y2 J
; ^' r* E9 `) H% D
这时有: - 6 x(n) = x(n) + 1;
- K>>
- Type dbquit to exit debug mode.2 \% C' B0 } q
: {. V. w* P$ k, M5 T& ?2 v/ y7 N, X, n; r* U: t
可见,dbstop比断点设置更加智能,控制起来更为方便。补充一句: - dbstop in file at location %在指定行设置断点. ?4 i* P( @7 o+ `: P
) Y# X1 _! X: [+ M% r: Z
& e" E, W" [' D6 J+ Q" h此时与F12等价。 所有dbstop,可配合return或者dbstop使用;" n# Q/ k% A* m
return:返回;1 p1 C4 M& p' q8 C1 A5 Q( O. q( u
dbstop:停止
7 a. L' q) z* ?* t; J/ z/ ]
- o" M/ L* _% R9 C ~4 C调试完成,需要清除所有断点: - 清除所有M文件的所有断点
6 g( r9 y+ g/ A
在Command Windows输入: - dbclear all( E; @4 c8 w2 [7 g+ o, j! v
1 L* J @7 q5 i# s
- E+ T- m" S7 E P g. n$ A* D- 清除文件名为mfile的文件的所有断点
) G& N3 C( l" U; w% J8 ]% }
在Command Windows输入: - dbclear all in mfile:' |( C& P1 ?6 ` H
0 E7 R( ]2 N1 d. S/ e( B2 ~
' J T2 W' O) I( |5 w
- 其他dbstop相关(前文所述,已满足基本Debug,此处列出其他操作,不再展开介绍,供感兴趣的朋友阅读):
9 n/ ^5 ~# p! Y
| (1)设置断点: * dbstop in mfile:在文件名为mfile的M文件第一个可执行语句前设断点;
" Y/ w# Q3 g2 s( @0 g* dbstop in mfile at lineno:在mfile的第lineno行设断点;
/ M9 M8 O: b# ? }* dbstop in mfile at subfun:当程序执行到子程序subfun时,暂时中止执行,并设断点;
" L+ p4 a' Z' R' V3 x- H* dbstop if error:遇到错误时,终止M文件运行,并停在错误行(不包括try...catch语句中检测到的的错误,不能在错误后重新开始运行);
4 N5 D1 f' K/ X- |1 ^$ k- i( N8 ~* dbstop if all error:遇到任何类型错误均停止(包括try...catch语句中检测到的的错误);
) z& @) M1 Q# X7 j* dbstop if warning:程序可恢复运行;! `; J, |& C" L% Z2 Q
* dbstop if caught error:当try...catch检测到运行时间错误是,停止M文件执行,可恢复运行;+ K+ O/ x+ H, d: E/ j; n0 D# `$ W7 }
* dbstop if naninf 或 dbstop if infnan (2)断点清除: * dbclear all:清除所有M文件中的所有断点;8 ?6 v4 u' D- N" y2 w" f% q. r
* dbclear all in mfile:清除文件名为mfile的文件中的所有断点;
1 `$ _$ _) N, q v* dbclear in mfile:清除文件名为mfile中第一个可执行语句前的断点;4 O( q1 X! |* u1 Y' t3 S
* dbclear in mfile at lineno:
% l9 J- Y! s8 M. e, X: u) w V* dbclear in mfile at subfun:2 {! S" A9 j2 ~0 f
* dbclear if error/warning/naninf/infnan: (3)恢复运行: * dbcount:从断点处恢复程序的执行,直到下一个断点或错误后返回Matlab基本工作空间; (4)执行一行或多行语句: * dbstep:执行下一个可执行语句;* J% ?5 Y. t! D/ X4 O+ P
* dbstep nlines:执行下nlines行可执行语句;6 Q# m' l! \8 W Z9 R& @$ k1 s3 J
* dbstep in:执行下一行可执行语句,如有子函数,进入;* i! j+ F2 j$ u
* dbstep out:执行函数剩余部分,离开函数时停止;9 ?+ O. B9 ]. g/ u
* 注:这四种都返回调试模式,如遇断点,中止; |
& }1 G7 N# {1 g" c. W# f
|