找回密码
 注册
关于网站域名变更的通知
查看: 438|回复: 2
打印 上一主题 下一主题

MATLAB程序调试基本方法分享

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-4-16 10:06 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
MATLAB程序调试基本方法分享
! R" ?5 ]8 P7 ]+ H9 G前言# y$ k: m4 h) C/ E* S8 h# U
    本文主要是对MATLAB程序调试中的一般方法进行总结,也是自己学习的记录。全文大致分为三个段落:
  |. G5 J8 b; x& J, {# ]1 C" ~% q' F  w: v8 a  T. i8 {
  1)代码内调试;. F" A2 P4 R8 q* B( s# E

% v* d& }: a0 c9 l0 I  2)断点调试方法;6 Q: D/ ?, {+ o- u( u
2 u3 e7 s) I1 @+ R/ B1 r% J/ f
  3)指令调试方法;
* T4 K/ K& e+ ?! \& n8 H$ J8 I0 E( F6 `9 U
本文主要为个人学习总结,并借鉴了前人的经验,相应链接在最后一并附上。2 r, S. S' y" Y


. j+ x( I( c, @" t3 s( w
  i7 t& d- H- [一、代码内调试
" }# S5 A% D) t5 A  x    A-打印变量
% I% d: x! o2 a5 Z2 R
  • z=hilbert(testdata');                   % 希尔伯特变换
  • a=abs(z)                                    % 包络线
  • fnor=instfreq(z);                       % 瞬时频率( E+ ]7 n+ n8 N  J( G7 C

& s) d/ y6 f# z" d* `
$ U! g  n: x/ {; c/ L3 l
上面的代码,如果希望检查a是否正常:去掉末尾的分号;,即可在Command Window查看到对应的输出信息,特别是当变量出现在function时,如果不输出,则在Workspace中无法直接查看,此时该操作较方便。9 ?+ F2 g" x8 \0 L8 _7 v, X
    B-局部执行
5 {1 {0 d! ?4 Y( i2 J
  • z=hilbert(testdata');                   % 希尔伯特变换
  • a=abs(z);                               % 包络线
  • fnor=instfreq(z);                       % 瞬时频率# t# l- Z' q% f1 }/ [
: {0 X- E) k7 }# s, k) {

+ u6 Q2 Y/ k: x1 Y# x5 C. V5 o! w如果希望对某一部分代码,进行调试,则完全没有必要每次都从头运行,这时局部执行较方便。仍是这段代码,如果希望仅仅执行高亮部分,则箭头选中并按F9,此时程序仅仅运行高亮部分,可利用这个方法调试局部代码。' ?; {4 E2 k" {7 S' f- Q4 j$ n
    C-配合绘图(该操作可以配合以下各类方法使用)! F& f. f+ R3 \" n# j
图形比数据更易于观察,在调试过程中打开Workspace中的变量(快捷键:Crtl + D),然后选择plot,即可根据需求对数据进行绘图,便于观察特性:3 H) @  f  v$ Z, _- d' q

! B5 L9 ?* N! S2 p/ S
例如选择需要观察的数据,分别选择bar以及suRF指令,即可绘制对应图形:

7 }- h& t2 D* T4 ]2 Y
4 x2 F, ?% P/ r% U2 t' r1 y
是不是也算方便?

3 q& [5 k4 c6 j4 E! c# X
2 G1 P8 q/ ]) V0 G: F

% a  m4 b# O6 _+ ~5 x* `0 {( z
二、断点调试方法

$ r( G8 r: p) F9 D
调试代码最经典的就是利用设置断点的方法,此处给出对应快捷键:
" {8 U6 u0 x' {. Q) V. |
  • F12:设置/取消 断点
  • F10:单步执行
  • F11:单步执行,且碰到function跳入函数内执行,F10则不会跳入,这是二者的明显区别
  • Shift + F11:跳入function之后,通过该指令推出function
  • F5:执行相邻两次断点见的所有指令,如:断点在for循环中,则F5一次,循环执行一次
  • Shift + F5:退出断点调试
    ' v8 {) L2 m/ q; d

7 [+ I: O& U- D# w9 n

( R5 f' b5 I( {$ r
三、指令调试方法
$ D' p; h8 E6 |9 m1 R3 ~
    A-keyboard + (return): Q& h6 n$ G  Z

经常碰到一些情况,如:矩阵相乘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);$ D5 X) a7 d& f+ M2 @( j
+ r1 P. u- D& D1 T

- @8 b+ u* B  p# I

但难以确定G还是G’,利用keyboard则可以修改为:

  • keyboard
  • P_tmp = real(m+1 - max_eig);
    : h, D5 W+ \$ o4 `, {1 h  w
' \) K. h( h4 R2 P% h

" z0 D. q  S5 m- V8 n
$ c6 J' c9 m; x, X, t9 c! ]" R

在进入K>> 之后,此时已经可以观察F、G的size,因此在Command Windows输入:

  • max_eig = max( eig(G'*pinv(F)*G) );
  • return;5 r2 d, q1 o1 u; x2 V
& W% k' g/ k6 S

$ t& H: W$ {2 {. c) h5 O6 V& q

即可保证程序顺利执行。

    B- try + (catch) + end

我们知道,matlab的代码是按行执行的,如果碰到错误行,则程序中断。try..catch可以使得可能出错的代码不影响后面代码的继续执行,也可以检查,排查,解决程序的一些错误,增强代码的鲁棒性和可靠性。

  • try ... end
    - ]8 K& u; _, S( }7 `- o* T  r5 W5 j
try...end用于尝试运行一段也许可能出错的代码,比如:
  • m = rand(3,4);
  • n = magic(5);
  • try
  •     a = m*n;
  •     disp(a)
  • end
  • disp(m)3 x/ J5 y  m+ u# B5 J
; x# C7 F) Q$ D0 b! R+ y
5 }  N; l6 L2 F, C1 h( M3 b! E
这段代码里面,a = m*n运行会出错,不满足矩阵乘法的原则。所以,a = m*n和disp(a)不执行,但后面的disp(m)亦然会执行。
  s* ?% M' B7 M! u% I- V5 x
  • try...catch...end1 B4 d" n  R7 P2 i

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)
    2 r9 D5 R3 ]9 E, ^/ c& m6 y
7 B% p2 N. J6 r3 d% ?' {: Y$ P

! }$ F/ M% D9 c0 b# x8 ]+ `+ `' E

这里面,当程序碰到 a = m*n;错误后,就会跳转到catch里面的语句,继续执行,有点类似于if...else...end。

    C-dbstop

  • dbstop if error
    ) v2 p; J$ W8 j3 r2 w4 r$ X% t6 T

在程序执行前输入:

  • dbstop if error
  • %================以下为main部分=================
  • ....%略) Z. _  u" ^1 H8 _# O2 l2 I8 @7 N5 ]

# [& i0 u. [' O' C

' c# |  I) |/ V4 D0 ]

 如果运行出现错误,matlab会自动停在出错的那行,并且保存所有相关变量。真心好用。

  • dbstop in file* R5 Z0 g. w+ G  |/ h- e

  在.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);* b: S$ A) P7 o9 Z( U) Q/ \

" G9 E" Q* T& k( y5 z& x6 V

5 m# j6 N' s2 v/ f  ^# ?- b% ~

效果如下:


, M  I& b- E7 }

即设置断点并运行至VMD程序内部,此时通过F10/F11/Shift F11等断点操作中的快捷键,即可进行调试,Command Windows输入dbquit即可退出。

  • dbstop in file at location if expression
    0 f( M) e% E0 x+ J! l7 o5 I5 @, l

比如有myprogram.m, 如下:

  • clear all;
  • close all
  • clc;
  • x = ones(1,10);
  • for n = 1:10
  •   x(n) = x(n) + 1;
  • end% O! R- d, E" S3 Q* U5 A

4 c5 j: y* r: u" n, P
' {1 g+ l: I2 j5 f

设置一个断点在 n >= 4时(对应程序位置为第6行),然后再运行程序:

  • dbstop in myprogram at 6 if n>=4;
  • myprogram;% n* `' J, u( x* N' _0 L

. U0 u$ K3 M1 p

( P  s; v  }' u8 R+ t

  这时有:

  • 6   x(n) = x(n) + 1;
  • K>>
  • Type dbquit to exit debug mode.
    / `/ d" T/ p/ W) b: A# s; y
! z6 f* p! j9 T/ d* v( N

' j  o( l+ P4 ?& l0 n- T5 }

可见,dbstop比断点设置更加智能,控制起来更为方便。补充一句:

  • dbstop in file at location   %在指定行设置断点
    2 h% _: n) Q( n, _7 p6 _( d( k) J
/ l6 S  F% X4 R. R4 @, z
9 f$ Z' p; R8 S7 o- }7 m  C% L

此时与F12等价。

所有dbstop,可配合return或者dbstop使用;, w9 O  Q! _  Q
  return:返回;
* a& A3 R6 O! j; G' |! Q6 c  dbstop:停止

0 Y8 e1 o8 J1 i
" @* A$ a5 x" n$ t- Q- }7 O& ]- f

调试完成,需要清除所有断点:

  • 清除所有M文件的所有断点
    ' f) y$ D& p, W' X: U

在Command Windows输入:

  • dbclear all" n$ m$ t' ]! y" J0 D6 _

4 v; c; N1 a( p, m  w% ]( M

. q! u1 u0 ?' e4 T3 Y6 z
  • 清除文件名为mfile的文件的所有断点
    8 X1 H" B4 Z6 r" D! ]

在Command Windows输入:

  • dbclear all in mfile:1 t# O0 C3 U5 e7 r/ k$ @4 ?* Y5 l

  [3 s/ P; B% ], n2 e) \. o7 t. Z  g

. _( j" d* F. _, n6 d
  • 其他dbstop相关(前文所述,已满足基本Debug,此处列出其他操作,不再展开介绍,供感兴趣的朋友阅读):
    . T0 t& r/ H) ^' w* H
(1)设置断点:

* dbstop in mfile:在文件名为mfile的M文件第一个可执行语句前设断点;  
+ k( p  I7 r: Z8 I6 i- e" D* dbstop in mfile at lineno:在mfile的第lineno行设断点;  }3 Q+ o0 b! y! ]) r
* dbstop in mfile at subfun:当程序执行到子程序subfun时,暂时中止执行,并设断点;
1 q+ S* x9 S) ^1 `6 k6 y* dbstop if error:遇到错误时,终止M文件运行,并停在错误行(不包括try...catch语句中检测到的的错误,不能在错误后重新开始运行);' s3 m  l' g" z
* dbstop if all error:遇到任何类型错误均停止(包括try...catch语句中检测到的的错误);! D% \9 _; r: H
* dbstop if warning:程序可恢复运行;, F6 v$ c2 M. \# R- K( N% J  I) V; O
* dbstop if caught error:当try...catch检测到运行时间错误是,停止M文件执行,可恢复运行;, x6 k% g5 \3 B7 ?: |( D
* dbstop if naninf 或 dbstop if infnan

(2)断点清除:

* dbclear all:清除所有M文件中的所有断点;. P; n$ }  A; }* G3 H$ ~4 }+ S
* dbclear all in mfile:清除文件名为mfile的文件中的所有断点;3 f4 O' Q8 y2 F0 M1 I
* dbclear in mfile:清除文件名为mfile中第一个可执行语句前的断点;, P9 T- ^, N% p5 J5 x
* dbclear in mfile at lineno:1 m: ]" v7 p8 V7 V  o
* dbclear in mfile at subfun:
8 T& F: X$ S  [0 @1 t5 t% n1 J* dbclear if error/warning/naninf/infnan:

(3)恢复运行:

* dbcount:从断点处恢复程序的执行,直到下一个断点或错误后返回Matlab基本工作空间;

(4)执行一行或多行语句:

* dbstep:执行下一个可执行语句;
& ~7 z9 l' ^2 z6 ]7 y7 ^* dbstep nlines:执行下nlines行可执行语句;+ c. w0 D: e! M0 S0 j) }' Q/ i% q
* dbstep in:执行下一行可执行语句,如有子函数,进入;
2 i. C$ a" y- G$ u; {, H) m* dbstep out:执行函数剩余部分,离开函数时停止;6 i9 U# S8 E; h; L& [  O
* 注:这四种都返回调试模式,如遇断点,中止;

* F6 a4 f- ], x& E4 ]/ B  R- X+ p

该用户从未签到

2#
发表于 2020-4-16 18:22 | 只看该作者
楼主分享的MATLAB程序调试基本方法都是些很实用的方法。

该用户从未签到

3#
发表于 2020-4-20 15:57 | 只看该作者
很实用啊,楼主好人,谢谢分享。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-8-23 16:20 , Processed in 0.140625 second(s), 26 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表