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

MATLAB程序调试基本方法分享

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
MATLAB程序调试基本方法分享. P  u9 ]: z2 o  b8 o% [
前言1 r0 P3 r2 K2 H
    本文主要是对MATLAB程序调试中的一般方法进行总结,也是自己学习的记录。全文大致分为三个段落:* K6 Q7 v' Y  z0 y
9 n" R4 z0 Q* ?+ w1 E" A( H
  1)代码内调试;2 k8 t: G4 ^4 F6 H, N$ q" \
0 h- w  V* d% V$ R0 r! A
  2)断点调试方法;3 n1 e3 S  F  Y' z, N' ]! A% O# M
5 {4 }: W& X8 U3 u4 ]' y
  3)指令调试方法;
( w( R1 t; Q# c/ {; d3 b& G5 E+ K' y2 R! b& W
本文主要为个人学习总结,并借鉴了前人的经验,相应链接在最后一并附上。2 J% y- w' u- L  v9 B! C  s2 W( e2 b

5 X$ c3 p# g& N+ M4 i; v' s

* n: m  h9 R8 a8 N5 }6 e* o; I一、代码内调试
  T" y) D: T4 V: a    A-打印变量( k8 v% x- R( `2 m% _& @
  • z=hilbert(testdata');                   % 希尔伯特变换
  • a=abs(z)                                    % 包络线
  • fnor=instfreq(z);                       % 瞬时频率
    : }& s$ t* I6 ^4 N  u1 U
# [8 G* e" p; A% C
! o! d3 T5 T! [( W6 Y% Y+ m
上面的代码,如果希望检查a是否正常:去掉末尾的分号;,即可在Command Window查看到对应的输出信息,特别是当变量出现在function时,如果不输出,则在Workspace中无法直接查看,此时该操作较方便。. e+ {4 a( E9 I; J8 Q! x. D( d
    B-局部执行
" y/ N2 x" i. ?5 z
  • z=hilbert(testdata');                   % 希尔伯特变换
  • a=abs(z);                               % 包络线
  • fnor=instfreq(z);                       % 瞬时频率
    + Y- S  {. f5 Y5 n( @( ^- @
4 ?! L  ~' G/ }; R3 a9 t1 Z

+ B1 T2 w  F- m) B5 u; T' U如果希望对某一部分代码,进行调试,则完全没有必要每次都从头运行,这时局部执行较方便。仍是这段代码,如果希望仅仅执行高亮部分,则箭头选中并按F9,此时程序仅仅运行高亮部分,可利用这个方法调试局部代码。
& Q/ n! q. k3 t' f) \    C-配合绘图(该操作可以配合以下各类方法使用)6 X6 |! s2 x; G# N; |# _
图形比数据更易于观察,在调试过程中打开Workspace中的变量(快捷键:Crtl + D),然后选择plot,即可根据需求对数据进行绘图,便于观察特性:' t1 v% v) S, S. B4 }$ r

! ^7 K1 ^; o7 ^3 _6 _
例如选择需要观察的数据,分别选择bar以及suRF指令,即可绘制对应图形:
: d" T4 m1 D7 n+ g8 s/ p5 \1 J
3 W% |# U& S+ n7 l
是不是也算方便?
% f4 q1 O! ^, `7 S
1 i- g  P. r! [8 F
- q7 Z5 H& J! L. W' ~
二、断点调试方法
0 _( C1 r! B3 T- F! B0 z+ y
调试代码最经典的就是利用设置断点的方法,此处给出对应快捷键:
4 Q) `" D6 T( b  I8 @
  • F12:设置/取消 断点
  • F10:单步执行
  • F11:单步执行,且碰到function跳入函数内执行,F10则不会跳入,这是二者的明显区别
  • Shift + F11:跳入function之后,通过该指令推出function
  • F5:执行相邻两次断点见的所有指令,如:断点在for循环中,则F5一次,循环执行一次
  • Shift + F5:退出断点调试8 b1 q9 K! {8 l# P" o# [

% k+ x* N0 S3 f( T: M
7 V( d3 E8 }1 d1 N2 g
三、指令调试方法

6 r( ]3 ~" W( r3 l$ H3 s    A-keyboard + (return)
( u# i. }: ~4 \; Z* U% I. _& e

经常碰到一些情况,如:矩阵相乘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);1 h1 Y6 A8 U- R* I' B

, J; B* v6 D9 h- ~2 ?: }4 b( ~
. {9 {. k9 {# R0 u, }+ F2 i( r

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

  • keyboard
  • P_tmp = real(m+1 - max_eig);4 C0 O8 }* b- \1 i( e

7 n( F4 b3 a$ S5 a, d

2 \6 I8 v' C  d4 Z3 l
6 A. I( ~, v1 K" y$ s! L9 o, K

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

  • max_eig = max( eig(G'*pinv(F)*G) );
  • return;
    : `6 H- p9 S! t2 o& `- G  s

: a" N; m$ x- |' G; y5 @( z
2 z+ e, _  s$ I

即可保证程序顺利执行。

    B- try + (catch) + end

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

  • try ... end
    - p* N/ R, l1 z% Z; n8 C, c# o. `
try...end用于尝试运行一段也许可能出错的代码,比如:
  • m = rand(3,4);
  • n = magic(5);
  • try
  •     a = m*n;
  •     disp(a)
  • end
  • disp(m), `% B4 j+ F" C: C- }

2 f; f+ R! a" \8 X+ @& `$ E; r

% E3 Q( y- K0 O: s9 W3 ^* @这段代码里面,a = m*n运行会出错,不满足矩阵乘法的原则。所以,a = m*n和disp(a)不执行,但后面的disp(m)亦然会执行。+ j9 `3 k5 `+ e+ X- K0 K
  • try...catch...end
    2 w5 {/ E0 ?2 r3 x

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)
    0 ?4 Q/ I/ l1 {9 Q

! ]* l' S" @" e1 A3 l( _
8 `6 r7 ~1 H/ ~4 o( q% \! E& R& }) |

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

    C-dbstop

  • dbstop if error: K6 [: {* G7 S5 q

在程序执行前输入:

  • dbstop if error
  • %================以下为main部分=================
  • ....%略
    ! F# M# B+ L+ ^" N  w* W( q# ?
9 r' r, r, _  g4 e' ^" J

! y8 y7 h3 Y) S" F7 \8 U- G

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

  • dbstop in file0 X5 |4 [6 |: M! R3 ~: P. [

  在.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);8 U5 v3 b& e9 N, L$ u

8 |  Z* r# i- n: X* b
. P) A0 g! P$ m/ I

效果如下:


4 e; ~3 s' `+ w& e- z) ~0 t" H

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

  • dbstop in file at location if expression
    : x7 z. d) v5 t

比如有myprogram.m, 如下:

  • clear all;
  • close all
  • clc;
  • x = ones(1,10);
  • for n = 1:10
  •   x(n) = x(n) + 1;
  • end
    $ D/ t- J' d3 j5 F  O- U
7 G) B/ W# Z) s1 y; ?+ k5 j. [

1 V% k$ q; X& p0 X2 N; @9 z

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

  • dbstop in myprogram at 6 if n>=4;
  • myprogram;
    6 o8 B( ?* A. H; E( ^2 N
. \/ s! T9 z% i7 V0 r# q; ^, p
# }6 G! d0 ]" w# L- ~+ f. [

  这时有:

  • 6   x(n) = x(n) + 1;
  • K>>
  • Type dbquit to exit debug mode.% I( f. N3 D- r7 d: R  [6 [
1 e0 s! i0 o* ~  D* z: v3 A# y

1 {, v, N% u+ d0 F  D

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

  • dbstop in file at location   %在指定行设置断点2 j3 B2 ?/ p6 t- x: s9 H! q7 f
: y$ U4 s% |! \* O

$ i% {' r- j/ H$ K

此时与F12等价。

所有dbstop,可配合return或者dbstop使用;
1 p5 B4 H$ x$ l8 A5 T/ I" o/ C  return:返回;' _3 B  o2 Z$ C+ U
  dbstop:停止

$ g0 B# t9 ^3 h& R9 s/ D4 j
8 `& i6 U3 S' c/ ]

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

  • 清除所有M文件的所有断点
    ( [; ]# w7 {0 X. m  f! h

在Command Windows输入:

  • dbclear all
      z( a$ X; y) F  P) b# H7 |7 j
% v+ l  z' A9 K6 k

& b! S4 c- j1 _* h+ A( t0 Y
  • 清除文件名为mfile的文件的所有断点! J1 l. [- h( I* l

在Command Windows输入:

  • dbclear all in mfile:
    ) n- m, x, y9 q* B# d% H! D

2 g/ _% V( L7 A' X; S% N7 P# V) T0 E

; \3 v4 w- e/ }
  • 其他dbstop相关(前文所述,已满足基本Debug,此处列出其他操作,不再展开介绍,供感兴趣的朋友阅读):
    4 n. l6 b. c# g6 ^* n
(1)设置断点:

* dbstop in mfile:在文件名为mfile的M文件第一个可执行语句前设断点;  
. D7 X  v" S, T/ W) _# X* dbstop in mfile at lineno:在mfile的第lineno行设断点;6 s' t$ ~& _6 x# \3 K4 y; O3 U
* dbstop in mfile at subfun:当程序执行到子程序subfun时,暂时中止执行,并设断点;" b+ G* W. y' o) }
* dbstop if error:遇到错误时,终止M文件运行,并停在错误行(不包括try...catch语句中检测到的的错误,不能在错误后重新开始运行);0 u6 m+ p. }( ?
* dbstop if all error:遇到任何类型错误均停止(包括try...catch语句中检测到的的错误);0 M  V1 R, q: h' i6 e/ A
* dbstop if warning:程序可恢复运行;
4 ^. {% \% F6 d& o8 r* dbstop if caught error:当try...catch检测到运行时间错误是,停止M文件执行,可恢复运行;! n& J5 |, Q; ~! h2 i# k# X% q; U/ O
* dbstop if naninf 或 dbstop if infnan

(2)断点清除:

* dbclear all:清除所有M文件中的所有断点;
" \* s4 {7 y8 O$ Y% p* dbclear all in mfile:清除文件名为mfile的文件中的所有断点;
- W- n2 u! x. K3 z1 e: S* dbclear in mfile:清除文件名为mfile中第一个可执行语句前的断点;
: O1 ]5 ~3 P) B: ]/ c* dbclear in mfile at lineno:
5 a" Q* v! W) ~+ G7 W8 |* dbclear in mfile at subfun:3 P# J  t( o: i8 C: M5 l- i  \
* dbclear if error/warning/naninf/infnan:

(3)恢复运行:

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

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

* dbstep:执行下一个可执行语句;: ~0 j, B1 U' F- T6 ~
* dbstep nlines:执行下nlines行可执行语句;- c+ R) i' U9 d3 X
* dbstep in:执行下一行可执行语句,如有子函数,进入;
9 R6 E$ T% ^& |7 K7 }9 T; I* dbstep out:执行函数剩余部分,离开函数时停止;" P+ e% t% G! K1 ?( r) H- ]
* 注:这四种都返回调试模式,如遇断点,中止;

0 H7 ^! @6 x: n$ e/ J

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-7-23 07:53 , Processed in 0.109375 second(s), 26 queries , Gzip On.

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

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

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