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

MATLAB程序调试基本方法分享

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
MATLAB程序调试基本方法分享
; G0 z1 Q( k+ n7 o/ ^3 b* l8 c$ c$ P前言
7 K( z' W5 r2 W4 S* z, R$ W0 d: N    本文主要是对MATLAB程序调试中的一般方法进行总结,也是自己学习的记录。全文大致分为三个段落:
- c% F/ _9 g5 A" }2 }, N  n* M9 G" ]7 Y3 H& V$ A2 v! ?
  1)代码内调试;
7 v9 D2 ?7 Y$ ~8 e! V2 c
2 B# a* _: I! r6 i+ T) H$ Y  2)断点调试方法;) n+ u+ j( c! E# n& k# s; ~# v
! {* R1 s0 |) |/ t: g! z# ~
  3)指令调试方法;. w( V6 B& S9 X1 ^4 b& [

( R( w" @5 f1 a: U  ~2 _0 z+ u1 K% m本文主要为个人学习总结,并借鉴了前人的经验,相应链接在最后一并附上。, u/ g" O& I& Z' e5 q- K: _: _


  S2 k. R0 Q4 l, U1 J; |
9 ^+ `- p) v" h: \5 k: ?$ m一、代码内调试& @( c! b5 [8 n$ _% i
    A-打印变量
  O/ J$ b" _7 _/ L
  • z=hilbert(testdata');                   % 希尔伯特变换
  • a=abs(z)                                    % 包络线
  • fnor=instfreq(z);                       % 瞬时频率
    / T4 m, g5 v8 }; l/ M0 a  P
1 E7 W. j. Z4 V$ @9 s
, R8 |! \  p3 F8 k5 H1 r" f
上面的代码,如果希望检查a是否正常:去掉末尾的分号;,即可在Command Window查看到对应的输出信息,特别是当变量出现在function时,如果不输出,则在Workspace中无法直接查看,此时该操作较方便。9 {' o# o6 X" _/ \* P8 t
    B-局部执行; ^& W; l) _: ]% A
  • z=hilbert(testdata');                   % 希尔伯特变换
  • a=abs(z);                               % 包络线
  • fnor=instfreq(z);                       % 瞬时频率4 _5 v. u3 Z, F

5 M. H( g# \3 @/ v, o: P

' u' o: ?) [' l# q% e$ q/ c3 W如果希望对某一部分代码,进行调试,则完全没有必要每次都从头运行,这时局部执行较方便。仍是这段代码,如果希望仅仅执行高亮部分,则箭头选中并按F9,此时程序仅仅运行高亮部分,可利用这个方法调试局部代码。: ?4 x/ h! }1 Z* f
    C-配合绘图(该操作可以配合以下各类方法使用)
& i. j, }% A( b- u图形比数据更易于观察,在调试过程中打开Workspace中的变量(快捷键:Crtl + D),然后选择plot,即可根据需求对数据进行绘图,便于观察特性:
( g* x# I2 Y+ V* y1 U* E0 z" g

- K3 ], ]# @: B4 [$ t8 o; }% ?. h
例如选择需要观察的数据,分别选择bar以及suRF指令,即可绘制对应图形:

: j2 k- M# F& K- l9 b
/ K2 b/ b; _" y* ]" u( F- c
是不是也算方便?

' r3 H% c3 i! o9 I6 F& E

: G5 W% `" I! Q  v
7 {& g2 b, g2 B" c- {. F
二、断点调试方法
) \6 W8 D  J- W  c+ W9 q+ h# L# d2 `# ]
调试代码最经典的就是利用设置断点的方法,此处给出对应快捷键:
& r# t- ^4 `2 Z+ m3 x# q
  • F12:设置/取消 断点
  • F10:单步执行
  • F11:单步执行,且碰到function跳入函数内执行,F10则不会跳入,这是二者的明显区别
  • Shift + F11:跳入function之后,通过该指令推出function
  • F5:执行相邻两次断点见的所有指令,如:断点在for循环中,则F5一次,循环执行一次
  • Shift + F5:退出断点调试2 m: A- @; C, E+ J
! @4 |0 a2 B# T! ]9 x
4 q( K: S  X. N+ v
三、指令调试方法

) u' q0 f4 M4 n' I0 V, S    A-keyboard + (return)6 S8 S/ @  m- Y1 o7 g' {6 J+ y3 B

经常碰到一些情况,如:矩阵相乘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);) b9 `4 y' {: \. X/ V( B

) S( X2 @' V, w5 ]7 @8 h: h/ [

6 v# w6 H7 k5 u* N; E" S

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

  • keyboard
  • P_tmp = real(m+1 - max_eig);
    % j# V) B: ~3 U' G, q# m7 ?

" B7 V5 K: a, U7 u  a! L" P1 Q

# N" B' }: g0 o4 o1 @
. K: Q' q  G8 o3 W0 e2 g7 \/ R: y1 Q

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

  • max_eig = max( eig(G'*pinv(F)*G) );
  • return;$ g$ J. S) d4 M+ \% E

7 t- _4 y  O; G- Q& T; i9 u. j8 v
1 D$ B# T0 w) X

即可保证程序顺利执行。

    B- try + (catch) + end

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

  • try ... end
    + m5 K0 j1 H1 s* K" I8 D/ M, \
try...end用于尝试运行一段也许可能出错的代码,比如:
  • m = rand(3,4);
  • n = magic(5);
  • try
  •     a = m*n;
  •     disp(a)
  • end
  • disp(m)8 y# P. B1 Q; r5 O
6 d3 m, h+ X$ h: }- Y! [

% _5 V+ t5 @7 |# D6 Q9 L6 p7 {这段代码里面,a = m*n运行会出错,不满足矩阵乘法的原则。所以,a = m*n和disp(a)不执行,但后面的disp(m)亦然会执行。
/ l6 H4 \* P  ?
  • try...catch...end
    - C9 a1 \. s! _3 f7 ~

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)" q3 k4 `1 o1 _( |
7 Z$ N& r' ^6 n/ I& J2 n9 n  W# d
9 U% z- B- b5 G- T

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

    C-dbstop

  • dbstop if error
    . K% B" i6 [8 }. b

在程序执行前输入:

  • dbstop if error
  • %================以下为main部分=================
  • ....%略
    - K) |: a5 J3 n# M2 y
- \5 c& e9 m1 X& n0 d1 X
& M2 D6 u' M* z8 J2 T' v; X

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

  • dbstop in file
      i8 c7 D; a, r5 Z0 [) f& D  U

  在.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);! j4 W& d2 X, i) J) D

, o# [! v3 }! {2 k  i

7 b! c/ p8 d; J

效果如下:

" X) }0 G5 x3 s% K0 N

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

  • dbstop in file at location if expression
    7 P; H" q# C) m/ E1 [

比如有myprogram.m, 如下:

  • clear all;
  • close all
  • clc;
  • x = ones(1,10);
  • for n = 1:10
  •   x(n) = x(n) + 1;
  • end
    - N1 f, M& |# i, W# S

. B$ X8 d1 U. @. u6 j, ?  x+ n: Y

* N1 ]1 w; H& Y- A1 I+ P" u5 d

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

  • dbstop in myprogram at 6 if n>=4;
  • myprogram;
    8 H) a) p" l# f8 I- V% T
, e% V8 V7 s, g; s0 \; x( j! d& d5 w
& ~; x/ y- _8 x) a6 G6 ?. W( O5 D: u

  这时有:

  • 6   x(n) = x(n) + 1;
  • K>>
  • Type dbquit to exit debug mode.4 C5 @8 p4 j; O7 y
# V& I, q9 k4 l9 d

/ d' a$ C2 U; U; ]

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

  • dbstop in file at location   %在指定行设置断点: [- k$ X  c+ |( o# ?+ K0 \! D
' n$ H2 n! P, |. `: C2 D

( e( E6 F- y" g

此时与F12等价。

所有dbstop,可配合return或者dbstop使用;
# j7 v) ?9 R; ]% \5 \  return:返回;
) R1 o) v* y. V7 r  dbstop:停止

0 k/ B7 F5 \# W& g9 P' M" a. f! T6 K7 W" U

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

  • 清除所有M文件的所有断点
    $ O* ]1 B3 c! ]; b4 ?8 z

在Command Windows输入:

  • dbclear all& H) L4 r" t7 y9 s* c$ `( y2 }
% y0 c$ a4 _- ~5 t1 X3 @: _
5 p/ S! q( G6 r! L0 i! Z6 I6 y" u
  • 清除文件名为mfile的文件的所有断点
    ! M' _7 g+ h2 @" n3 |' t

在Command Windows输入:

  • dbclear all in mfile:4 X# G, ?9 i% I
- G  \; a3 t# ~" e% o2 P. \
/ J: l- M! I; y( V, E7 z
  • 其他dbstop相关(前文所述,已满足基本Debug,此处列出其他操作,不再展开介绍,供感兴趣的朋友阅读):
    7 A7 v' o& ]8 y( j8 i, I5 y, @
(1)设置断点:

* dbstop in mfile:在文件名为mfile的M文件第一个可执行语句前设断点;  
7 Z& v+ G) i" p2 X0 F* dbstop in mfile at lineno:在mfile的第lineno行设断点;
) z7 u1 p5 I1 P* dbstop in mfile at subfun:当程序执行到子程序subfun时,暂时中止执行,并设断点;& {# H* W# K* t& Q
* dbstop if error:遇到错误时,终止M文件运行,并停在错误行(不包括try...catch语句中检测到的的错误,不能在错误后重新开始运行);- c4 ~# i- ~; n$ _
* dbstop if all error:遇到任何类型错误均停止(包括try...catch语句中检测到的的错误);3 d/ f5 B( A2 k
* dbstop if warning:程序可恢复运行;
* e7 F6 y2 a3 q* a9 d' h' M* dbstop if caught error:当try...catch检测到运行时间错误是,停止M文件执行,可恢复运行;
6 Z- Q3 I0 ^! O& A* dbstop if naninf 或 dbstop if infnan

(2)断点清除:

* dbclear all:清除所有M文件中的所有断点;1 [( I( T# i$ f8 [5 o' n+ U3 M3 J
* dbclear all in mfile:清除文件名为mfile的文件中的所有断点;
6 p6 x  {7 m1 m3 x/ R' A+ A" p1 O* dbclear in mfile:清除文件名为mfile中第一个可执行语句前的断点;
, b  d/ O/ x1 X! b3 P* dbclear in mfile at lineno:
: p7 }) ~8 c5 V8 Y# M* dbclear in mfile at subfun:
- u/ H# X2 ?5 s# q, @* dbclear if error/warning/naninf/infnan:

(3)恢复运行:

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

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

* dbstep:执行下一个可执行语句;) P9 |4 q% ^1 u$ t! h) G
* dbstep nlines:执行下nlines行可执行语句;& D% K' K) i( _7 {6 h
* dbstep in:执行下一行可执行语句,如有子函数,进入;& |1 c: B( B1 e7 M
* dbstep out:执行函数剩余部分,离开函数时停止;' J7 V  E% s+ P; p$ L# S( N
* 注:这四种都返回调试模式,如遇断点,中止;


$ K- {$ M" _( |; I# e- d

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-11-24 03:50 , Processed in 0.156250 second(s), 26 queries , Gzip On.

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

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

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