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

MATLAB程序调试基本方法分享

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
MATLAB程序调试基本方法分享
0 j+ r! }; I( T+ e/ m* |  |8 r前言) z) `4 _  n) B, p+ N' d" Q" N
    本文主要是对MATLAB程序调试中的一般方法进行总结,也是自己学习的记录。全文大致分为三个段落:
# ^- t8 j+ G" E7 R
: |9 @/ U6 i9 L. X9 \  1)代码内调试;+ k1 V" S# w5 @" L+ y

6 k2 _. k  |" v; k, x8 P1 w2 c  2)断点调试方法;
* E. g8 {$ d* |$ Z& I$ K
  B$ |/ a3 X. l# I5 a  3)指令调试方法;; j: G/ _. v/ H$ y
' d5 _) s  B2 H9 h
本文主要为个人学习总结,并借鉴了前人的经验,相应链接在最后一并附上。
. J1 ?9 }5 ~4 l6 g
% `! n2 v3 c6 ~" o/ d5 X, u. d
0 m$ o# q% s& N; W
一、代码内调试
; V, x6 W. H, ~  ]5 r3 T    A-打印变量8 @$ [( G$ Z- k* R* H1 O
  • z=hilbert(testdata');                   % 希尔伯特变换
  • a=abs(z)                                    % 包络线
  • fnor=instfreq(z);                       % 瞬时频率+ X* _9 O: G+ b8 R: }

* C9 ~5 J5 {4 O7 z. M( M
% x: S- @) y3 I% `: d; m
上面的代码,如果希望检查a是否正常:去掉末尾的分号;,即可在Command Window查看到对应的输出信息,特别是当变量出现在function时,如果不输出,则在Workspace中无法直接查看,此时该操作较方便。" M" G) h' [2 [. M' J7 J
    B-局部执行
$ d; O5 k" l0 q) W
  • z=hilbert(testdata');                   % 希尔伯特变换
  • a=abs(z);                               % 包络线
  • fnor=instfreq(z);                       % 瞬时频率) p2 U9 t* f. E5 F: Y6 }4 g' c( P$ a
0 \  N# W- O2 F

8 u& D; H$ Q; J( a* W* m2 t如果希望对某一部分代码,进行调试,则完全没有必要每次都从头运行,这时局部执行较方便。仍是这段代码,如果希望仅仅执行高亮部分,则箭头选中并按F9,此时程序仅仅运行高亮部分,可利用这个方法调试局部代码。
- G2 @+ {4 h* i# }6 a    C-配合绘图(该操作可以配合以下各类方法使用)* |1 |3 f  r' P
图形比数据更易于观察,在调试过程中打开Workspace中的变量(快捷键:Crtl + D),然后选择plot,即可根据需求对数据进行绘图,便于观察特性:
5 C6 j  L3 U% ~7 ^/ j% T  l# I
1 a# Q  u  \; c8 O! ]" r7 S& D
例如选择需要观察的数据,分别选择bar以及suRF指令,即可绘制对应图形:
/ R& d: f8 {. j2 }% i% k

4 V. W+ |# ?2 A& }
是不是也算方便?
. z# M3 c- ]. I! ]; `8 S
# P0 \9 C# F3 L2 V5 T! ]
% F4 }+ ~7 d* s& X, ^
二、断点调试方法

% p9 E$ ~2 k! h% ?+ R0 i
调试代码最经典的就是利用设置断点的方法,此处给出对应快捷键:

+ o) i# n- u% d) n$ T
  • F12:设置/取消 断点
  • F10:单步执行
  • F11:单步执行,且碰到function跳入函数内执行,F10则不会跳入,这是二者的明显区别
  • Shift + F11:跳入function之后,通过该指令推出function
  • F5:执行相邻两次断点见的所有指令,如:断点在for循环中,则F5一次,循环执行一次
  • Shift + F5:退出断点调试
    $ x9 v2 l; W4 g  B
; J. Z0 M8 S# X4 h8 }- |
4 _+ W' h- D; v- e% Q: ]" E* m
三、指令调试方法

( R! y8 ]1 A3 Y    A-keyboard + (return)3 k% T# o! G' _  E7 s3 Y' M: x& k

经常碰到一些情况,如:矩阵相乘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& _$ l( M) C$ f

! R; x/ o( [/ ]" I( t6 g* D8 `6 }
# `3 \* |3 W2 ~) P- a: M

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

  • keyboard
  • P_tmp = real(m+1 - max_eig);
    ( a$ ~8 R$ a. [
0 y+ M7 W& u6 \/ [

% X! }5 e; L: Z( k: _5 T1 X* `& z9 O9 m$ w  ?* X

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

  • max_eig = max( eig(G'*pinv(F)*G) );
  • return;/ q: h6 ]0 L. x. c4 n
1 q. f5 P6 w  V9 u5 P
2 z  b; A$ [6 D; B6 q2 e0 S% ~- d

即可保证程序顺利执行。

    B- try + (catch) + end

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

  • try ... end8 I+ }7 h* x7 q1 P: f
try...end用于尝试运行一段也许可能出错的代码,比如:
  • m = rand(3,4);
  • n = magic(5);
  • try
  •     a = m*n;
  •     disp(a)
  • end
  • disp(m)" L: m  }7 a' M, E; m7 p

% G, X# J0 b" ?* S5 P$ m: Q" }
' H8 N: m% A+ T0 W1 b5 Q' Y
这段代码里面,a = m*n运行会出错,不满足矩阵乘法的原则。所以,a = m*n和disp(a)不执行,但后面的disp(m)亦然会执行。: l: D# g  W9 N7 a; }8 _( k
  • try...catch...end
    * \* W# m4 w; u& v

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)# e  K% g: U/ y+ x9 l

6 E1 }( P. p* ~, H0 R; J0 K2 i2 ^6 A

! u& }; K' o( g* C9 m

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

    C-dbstop

  • dbstop if error
    : t, s7 y) b; Y4 \) n, E

在程序执行前输入:

  • dbstop if error
  • %================以下为main部分=================
  • ....%略
    # t; G5 j& y. u# c8 T! p% k% l
. @) h' _* g9 t

% |; e( [! ~# k" q: k

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

  • dbstop in file
    7 K: i  h! V/ U' {8 c6 r! W2 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);& J: I3 u; H# u$ j# X

8 ~# D+ B% ]  H, ?9 m
% X3 b2 `* P' ~7 ~3 Z$ ], T

效果如下:

7 I# a) L  V6 u  O6 G  ]

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

  • dbstop in file at location if expression
    # S% m% c/ q% L% S

比如有myprogram.m, 如下:

  • clear all;
  • close all
  • clc;
  • x = ones(1,10);
  • for n = 1:10
  •   x(n) = x(n) + 1;
  • end% ]* c% O6 h# F) a) \! k+ {
& x: m+ M/ _% s+ |8 P( \

! j# j; t& Y5 ?( k$ D" R

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

  • dbstop in myprogram at 6 if n>=4;
  • myprogram;8 a" x! Y$ Q! s

% X" K; f: j& J3 M+ g
5 ]& b; d" [; ^( x' {$ C

  这时有:

  • 6   x(n) = x(n) + 1;
  • K>>
  • Type dbquit to exit debug mode.
    7 ~& [/ e' q/ Z( `/ f1 F( b

" S" c0 _" i# g  [, O
- o/ B% S* f* F0 m" A

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

  • dbstop in file at location   %在指定行设置断点' }, Y3 P" }' E' l
4 M0 @. Y* p- r- v6 n
9 F7 e8 {% ^8 L; g) b' `/ E

此时与F12等价。

所有dbstop,可配合return或者dbstop使用;
& A0 _" ~$ X# J  return:返回;
& j: O2 p6 p4 G1 x( s& ~; ^0 P  dbstop:停止

) j4 m" L8 o, e: h7 a2 @% m( A. }+ ^( n. N+ I, s7 d3 V* i% L8 p  |4 \

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

  • 清除所有M文件的所有断点! |/ J* x. k( C, _

在Command Windows输入:

  • dbclear all) K* I4 ^9 t4 g* C7 [( x
9 L* t3 e" X) Y8 W5 p  c& X( |

/ ]$ W/ l0 ^* h. p# o$ J" ?% O& @
  • 清除文件名为mfile的文件的所有断点
    " w9 [8 P( U1 V5 r2 Q( U2 f

在Command Windows输入:

  • dbclear all in mfile:
    . }+ Y+ n$ M* ^. J
! L0 R5 X1 |' w: y

( ^+ f& B: u/ w) I$ K
  • 其他dbstop相关(前文所述,已满足基本Debug,此处列出其他操作,不再展开介绍,供感兴趣的朋友阅读):
    ; w+ h: U) s2 S) |: S
(1)设置断点:

* dbstop in mfile:在文件名为mfile的M文件第一个可执行语句前设断点;  
: q: b6 P  q+ O- I: F* dbstop in mfile at lineno:在mfile的第lineno行设断点;
; ?3 e& }) I/ e% v9 [* dbstop in mfile at subfun:当程序执行到子程序subfun时,暂时中止执行,并设断点;
3 O4 Z/ t' W3 R1 H1 L* dbstop if error:遇到错误时,终止M文件运行,并停在错误行(不包括try...catch语句中检测到的的错误,不能在错误后重新开始运行);
( \$ Q1 Z4 q' q5 t0 }1 i* dbstop if all error:遇到任何类型错误均停止(包括try...catch语句中检测到的的错误);
( I0 F* F2 w1 A# D4 _& r  N: ]8 O* dbstop if warning:程序可恢复运行;
/ A5 i) D1 {% j+ c* dbstop if caught error:当try...catch检测到运行时间错误是,停止M文件执行,可恢复运行;1 F% b6 ^1 H1 U0 V# K/ B
* dbstop if naninf 或 dbstop if infnan

(2)断点清除:

* dbclear all:清除所有M文件中的所有断点;
+ q8 G/ d* p- q) `* dbclear all in mfile:清除文件名为mfile的文件中的所有断点;( U7 Q9 m- r- ~& W
* dbclear in mfile:清除文件名为mfile中第一个可执行语句前的断点;
3 A+ c: d5 P7 }* i5 n* dbclear in mfile at lineno:
  p" `6 _5 G9 w  [* dbclear in mfile at subfun:
2 F% w6 i2 g0 b5 Q( i6 |* dbclear if error/warning/naninf/infnan:

(3)恢复运行:

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

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

* dbstep:执行下一个可执行语句;/ v6 @9 k8 o# N6 x2 ]+ `5 ]7 L2 H
* dbstep nlines:执行下nlines行可执行语句;
) }$ l% v5 @9 w# F! t1 I' @* dbstep in:执行下一行可执行语句,如有子函数,进入;
  ^/ T, }9 @& H" P$ Y; F  F* dbstep out:执行函数剩余部分,离开函数时停止;
  f9 C$ X+ H8 z) m6 E* 注:这四种都返回调试模式,如遇断点,中止;

' J" q4 c! D6 v) @, S; S

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

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

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

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

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