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

MATLAB程序调试基本方法分享

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
MATLAB程序调试基本方法分享& t  U" y% g9 k2 |8 T
前言
; G8 ^  ?  q: {: u5 Y    本文主要是对MATLAB程序调试中的一般方法进行总结,也是自己学习的记录。全文大致分为三个段落:
! H' |. j0 C1 b' M( |7 M  A
: h3 d! U+ O  {( T+ w* Y* U  s  1)代码内调试;$ s) V# G# D7 K1 d
# S+ C0 L5 `2 C7 X
  2)断点调试方法;
. {3 n. i, H  l, r% j
. r3 r7 a' Q/ y0 r  3)指令调试方法;) A0 U7 Y" S# J5 \0 ], ?
3 R+ z7 t) n1 H6 k; X, l  y
本文主要为个人学习总结,并借鉴了前人的经验,相应链接在最后一并附上。
* o8 G- F; l8 D3 \: O2 }: D, T  U7 T

4 C# _5 Y& F. h3 J2 A+ g) L+ y' S: l7 S$ [" E0 X7 l+ y2 B: O
一、代码内调试  s/ a, }3 ~2 z9 ]: c- T" `3 J6 r( D
    A-打印变量) `/ q( s8 V/ T  x( u% o3 o
  • z=hilbert(testdata');                   % 希尔伯特变换
  • a=abs(z)                                    % 包络线
  • fnor=instfreq(z);                       % 瞬时频率$ a+ N6 H, N: l: A& a
) f* W! r( R0 q+ F9 [( }3 L
5 y( V' K5 S% L* C. _. |* c8 D  t. P3 \
上面的代码,如果希望检查a是否正常:去掉末尾的分号;,即可在Command Window查看到对应的输出信息,特别是当变量出现在function时,如果不输出,则在Workspace中无法直接查看,此时该操作较方便。$ W3 V% V3 M$ l" m$ J' r
    B-局部执行
, N3 N4 ^7 I6 A
  • z=hilbert(testdata');                   % 希尔伯特变换
  • a=abs(z);                               % 包络线
  • fnor=instfreq(z);                       % 瞬时频率# p) J! Q7 y) n4 b+ g

' {  B7 I& S1 a/ A
& n2 B4 b- y2 M$ h! e
如果希望对某一部分代码,进行调试,则完全没有必要每次都从头运行,这时局部执行较方便。仍是这段代码,如果希望仅仅执行高亮部分,则箭头选中并按F9,此时程序仅仅运行高亮部分,可利用这个方法调试局部代码。3 J4 t4 g% t3 u1 K. S
    C-配合绘图(该操作可以配合以下各类方法使用)) f) t# ^! h; ?  ^# N9 n, U; X
图形比数据更易于观察,在调试过程中打开Workspace中的变量(快捷键:Crtl + D),然后选择plot,即可根据需求对数据进行绘图,便于观察特性:6 r% v0 q+ W8 ^7 w; W/ m! s$ `. U
" h1 C! D5 D/ a6 I; M% N- |5 f
例如选择需要观察的数据,分别选择bar以及suRF指令,即可绘制对应图形:

& G0 J) D6 q- o  ]
( G4 i7 q8 r/ Y( f# _2 z
是不是也算方便?

" C  r& w" H) O% ]- z1 y

6 H* H3 v/ b: J8 _2 m9 F- A

) r5 ]7 ^3 l! Q% w1 `: C+ o
二、断点调试方法

: M. w  [: J8 ~* g  C
调试代码最经典的就是利用设置断点的方法,此处给出对应快捷键:
' N- R; I: Y1 l! v& U/ `; {
  • F12:设置/取消 断点
  • F10:单步执行
  • F11:单步执行,且碰到function跳入函数内执行,F10则不会跳入,这是二者的明显区别
  • Shift + F11:跳入function之后,通过该指令推出function
  • F5:执行相邻两次断点见的所有指令,如:断点在for循环中,则F5一次,循环执行一次
  • Shift + F5:退出断点调试2 E& @' i8 t/ K' ~( j$ n

+ `0 u, h! M3 f& x' g
' ^# h( H; W5 N) k  K: x1 ?
三、指令调试方法
: {6 F/ u% ?+ \; H7 [, ]
    A-keyboard + (return)
! J. [% A$ o/ D" B' ^7 E( v: a

经常碰到一些情况,如:矩阵相乘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);0 D& @% \3 }. a# _! z

! @1 r; u& i9 h" N
+ N, w) T2 O% Z4 m

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

  • keyboard
  • P_tmp = real(m+1 - max_eig);
    " b/ ~0 [3 Y" v& u$ ]2 G. T
& ^4 i- P2 @) \( Q

( s/ D$ k8 ]) L* o8 o" e9 G- G& X

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

  • max_eig = max( eig(G'*pinv(F)*G) );
  • return;
    , [! L4 Y8 Z, ]( H

# n6 }/ p3 }5 C' p' x

* y# M4 Y" T1 M; T

即可保证程序顺利执行。

    B- try + (catch) + end

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

  • try ... end: `) U. X: T4 f8 z
try...end用于尝试运行一段也许可能出错的代码,比如:
  • m = rand(3,4);
  • n = magic(5);
  • try
  •     a = m*n;
  •     disp(a)
  • end
  • disp(m), w9 i, ^, G/ B: f# _# Y8 _& R
  x$ e5 i% s, Q; w
+ H: t8 \2 |( v" h. \+ K- a$ d
这段代码里面,a = m*n运行会出错,不满足矩阵乘法的原则。所以,a = m*n和disp(a)不执行,但后面的disp(m)亦然会执行。* P7 S2 ~5 ~8 L5 y, H. S$ P( h
  • try...catch...end
    & O( M% [3 V7 T# u8 N

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)
    6 C* @3 e* V9 E

: W' E* H- Y! V' v, q
# |8 S8 K. u# u; `3 P$ u2 W8 S# N

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

    C-dbstop

  • dbstop if error
    * ~" a% U) ^5 j7 |8 X1 [6 e

在程序执行前输入:

  • dbstop if error
  • %================以下为main部分=================
  • ....%略
    % F7 k: H8 S, u- M
% p, g0 t; X7 L) P# D3 N/ E+ K0 I
( A* X, H% d. ]- w: S- e" r0 N" R

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

  • dbstop in file! s* {' ]. `5 Q0 O0 P' e* c& L

  在.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);# U6 X- m- Y; J/ O) g" k; j

3 A) e$ s' R2 g$ B8 d

, V# ~+ R4 t( }2 v/ i$ d

效果如下:

! V! t; w" h) E, G5 P4 r

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

  • dbstop in file at location if expression
    / p. ]0 s6 p- `, J: q

比如有myprogram.m, 如下:

  • clear all;
  • close all
  • clc;
  • x = ones(1,10);
  • for n = 1:10
  •   x(n) = x(n) + 1;
  • end
    8 G! M% R4 L3 d4 C4 V

& t8 {, v3 O% t% J& P! H! v

9 S4 p. N. k' R) J! g+ \

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

  • dbstop in myprogram at 6 if n>=4;
  • myprogram;
    % t5 q1 a  l/ Z

7 r. U$ L  K2 j
. R7 C$ M- a( Q1 J. U! B. P

  这时有:

  • 6   x(n) = x(n) + 1;
  • K>>
  • Type dbquit to exit debug mode.
    - j. m5 J. M' G
% H- h, ~! t5 V  Y' N6 I( `
: k! ]' o/ {8 W2 s9 S6 F

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

  • dbstop in file at location   %在指定行设置断点
    / l& ?4 i# c, C' `' S. b# q

6 w: r$ g6 L* j) g) h
2 V) w" Y4 Z5 Q( d& n

此时与F12等价。

所有dbstop,可配合return或者dbstop使用;
$ R" J3 c/ z8 S' {6 n5 L% U% T* E. U- y  return:返回;
3 `% C* [) N2 I2 r  dbstop:停止
, ^. ?% z  Z/ F/ z! V3 D: c7 J

' e% o! T4 P( T

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

  • 清除所有M文件的所有断点9 b& w: ]4 s, i  O

在Command Windows输入:

  • dbclear all
    * q# Z! `1 H% ]9 J. h

; d: o* Y/ U1 y6 B( b
8 H" [8 y$ J- ?# s) T3 [
  • 清除文件名为mfile的文件的所有断点
    : {$ r5 J. g& o9 u

在Command Windows输入:

  • dbclear all in mfile:
    * z) n( e6 }  ~9 {. y- i

* D- `7 D; B# ^( y

7 i# T3 C- n* S5 _
  • 其他dbstop相关(前文所述,已满足基本Debug,此处列出其他操作,不再展开介绍,供感兴趣的朋友阅读):
    ' e3 Z  Q# R& ^( H( u$ z+ Z
(1)设置断点:

* dbstop in mfile:在文件名为mfile的M文件第一个可执行语句前设断点;  
+ }- Y" N! S7 S4 }& g* dbstop in mfile at lineno:在mfile的第lineno行设断点;( b  W6 [3 z' u% W- H
* dbstop in mfile at subfun:当程序执行到子程序subfun时,暂时中止执行,并设断点;
8 U+ D* f5 d% l% i4 a* dbstop if error:遇到错误时,终止M文件运行,并停在错误行(不包括try...catch语句中检测到的的错误,不能在错误后重新开始运行);
7 E) S1 B) t% ^6 G; X7 R* dbstop if all error:遇到任何类型错误均停止(包括try...catch语句中检测到的的错误);7 \0 _7 N2 e4 f& s0 l' F0 k
* dbstop if warning:程序可恢复运行;
: n6 p' a( R5 x4 @% c7 r1 ~* dbstop if caught error:当try...catch检测到运行时间错误是,停止M文件执行,可恢复运行;, c/ [2 Y! R: v" i! _0 M, @
* dbstop if naninf 或 dbstop if infnan

(2)断点清除:

* dbclear all:清除所有M文件中的所有断点;. o2 `% p" A2 i  C0 j
* dbclear all in mfile:清除文件名为mfile的文件中的所有断点;: e( ~( ^* E5 t/ B. c
* dbclear in mfile:清除文件名为mfile中第一个可执行语句前的断点;
# s7 W+ w# V; S5 x* dbclear in mfile at lineno:3 r- K: D# R0 o
* dbclear in mfile at subfun:
% Y) Z' o! x" D3 ?6 [% i) ^* dbclear if error/warning/naninf/infnan:

(3)恢复运行:

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

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

* dbstep:执行下一个可执行语句;
+ H8 o( I& Q7 a5 {; s* B+ M6 E* dbstep nlines:执行下nlines行可执行语句;
% ~# x4 T! Y9 t* dbstep in:执行下一行可执行语句,如有子函数,进入;
; r1 m0 C  R# G! b& z* dbstep out:执行函数剩余部分,离开函数时停止;
( L' d" M' X$ R7 q* l* 注:这四种都返回调试模式,如遇断点,中止;


/ I" {- X  D6 J8 S& g; g& L

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

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

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

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

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