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

MATLAB程序调试基本方法分享

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
MATLAB程序调试基本方法分享3 k7 v, G( l  i6 v% u2 i: K. K
前言
- |6 E& y7 `5 k: Y/ V. ~8 A    本文主要是对MATLAB程序调试中的一般方法进行总结,也是自己学习的记录。全文大致分为三个段落:" l* B$ _! p  W- b4 I6 d3 S
7 `: e; H0 T' ^( V- n2 u/ B
  1)代码内调试;
$ s  w$ Z, L$ b! D0 y1 o5 q# B, I! ~" s8 X3 B# L7 t  Q8 ?
  2)断点调试方法;
% o7 f: r+ t- ^" |  |. b3 ?
) G. H, j1 r/ W  3)指令调试方法;
: A; K/ J5 K4 h$ q$ R' P  j, c& |
& B+ W5 F. e+ o% i本文主要为个人学习总结,并借鉴了前人的经验,相应链接在最后一并附上。1 k- ]+ h0 \1 j5 L$ r, g8 L

% P5 w9 H' g9 |

( U6 x$ F( w: _$ Z8 T6 N, w/ z3 n一、代码内调试
& p# k! J* N1 E' u    A-打印变量/ k9 r4 Z0 p( U7 D. l  Z# v' X4 C" _
  • z=hilbert(testdata');                   % 希尔伯特变换
  • a=abs(z)                                    % 包络线
  • fnor=instfreq(z);                       % 瞬时频率
    : w8 o' E. S6 G4 Z: ]

# n0 V5 R7 K$ `6 \$ b: d" i$ v
# M2 s1 o( ]2 w2 p8 C1 c8 D2 P
上面的代码,如果希望检查a是否正常:去掉末尾的分号;,即可在Command Window查看到对应的输出信息,特别是当变量出现在function时,如果不输出,则在Workspace中无法直接查看,此时该操作较方便。
3 y, \/ v. t: B. {6 y" D7 x5 o    B-局部执行
- Q! `0 J, V0 f( ]# s# n( `
  • z=hilbert(testdata');                   % 希尔伯特变换
  • a=abs(z);                               % 包络线
  • fnor=instfreq(z);                       % 瞬时频率
    * z+ d0 p' b3 R& c1 B
3 I4 T3 O5 ]8 B8 h! X8 @% ^

7 O+ p9 e2 |. h5 w! E% J如果希望对某一部分代码,进行调试,则完全没有必要每次都从头运行,这时局部执行较方便。仍是这段代码,如果希望仅仅执行高亮部分,则箭头选中并按F9,此时程序仅仅运行高亮部分,可利用这个方法调试局部代码。
2 z7 U" b5 A6 e    C-配合绘图(该操作可以配合以下各类方法使用): p+ D" F% {' B& i1 E
图形比数据更易于观察,在调试过程中打开Workspace中的变量(快捷键:Crtl + D),然后选择plot,即可根据需求对数据进行绘图,便于观察特性:) l! l2 v, F8 G. B
1 r' @3 a% h+ l9 f; A
例如选择需要观察的数据,分别选择bar以及suRF指令,即可绘制对应图形:

& T7 U8 ]$ R9 q7 h% }
* u/ z: h/ N. t- g
是不是也算方便?
) g. T/ U! M: V+ L' A. N
3 F. x. P1 Z' @; P$ v$ b

1 p" j4 w; v$ H0 B; Z! {: E& B
二、断点调试方法
( }' n( q6 f3 \0 B/ a, Y, m
调试代码最经典的就是利用设置断点的方法,此处给出对应快捷键:
9 G/ a7 A4 c+ x( e/ m1 }
  • F12:设置/取消 断点
  • F10:单步执行
  • F11:单步执行,且碰到function跳入函数内执行,F10则不会跳入,这是二者的明显区别
  • Shift + F11:跳入function之后,通过该指令推出function
  • F5:执行相邻两次断点见的所有指令,如:断点在for循环中,则F5一次,循环执行一次
  • Shift + F5:退出断点调试
    . m; Z) _! F) |% V8 B& `
# h" e# i0 U. _

& z2 J" ^. b  m( L: J
三、指令调试方法

  K5 S+ \$ X$ Y7 H6 x5 [/ l+ c5 l    A-keyboard + (return)
: S" I" j& O' ]

经常碰到一些情况,如:矩阵相乘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);( q& y8 I2 K! f. M& g
: T( q, d5 H* H: }! _$ J1 ^

. |; z3 e0 C% \+ D

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

  • keyboard
  • P_tmp = real(m+1 - max_eig);- Q. @( R- J: }+ T

4 T7 {( z4 G' k7 m: P# y
4 X# O2 P) L0 f  v( ^- ~

1 I8 J- z1 c/ k2 d9 @, @

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

  • max_eig = max( eig(G'*pinv(F)*G) );
  • return;
    ! n+ Z% i. u$ G. y% o4 [' d5 C. l( S

% c  ~5 G( ?; e8 |8 u/ z1 m; u# G

# S$ j5 O5 O' e' j- x6 o: x

即可保证程序顺利执行。

    B- try + (catch) + end

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

  • try ... end, U0 X/ V& }3 ?4 K
try...end用于尝试运行一段也许可能出错的代码,比如:
  • m = rand(3,4);
  • n = magic(5);
  • try
  •     a = m*n;
  •     disp(a)
  • end
  • disp(m)
    3 p6 [. b  U; y0 N8 t# p
( M3 K( f* U9 G/ r  Y0 m/ w8 s/ _

4 {% o' `" ]4 w. L, b; r4 y% q/ e: w这段代码里面,a = m*n运行会出错,不满足矩阵乘法的原则。所以,a = m*n和disp(a)不执行,但后面的disp(m)亦然会执行。
+ y  p) q: T( d1 i$ J; T0 P
  • try...catch...end' T1 {1 @) p& H

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)
    7 S: R: b/ [  Y% i8 C8 T
) }' i: j# k8 O' Z3 d( y5 G

5 e, U$ F- d. P0 ~$ U. {

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

    C-dbstop

  • dbstop if error; I# I  Z+ J  i0 W! O) T# x

在程序执行前输入:

  • dbstop if error
  • %================以下为main部分=================
  • ....%略" P/ U4 F& _+ r6 P1 `9 e
% @& }) C' I2 Z6 k+ J
, h) `* ?* x( S8 h# @

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

  • dbstop in file
    4 I8 s) O, W" W" C! D! p4 Z" d

  在.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! M; h% |! H5 E

0 g& H2 D" b4 }3 k$ m$ n$ n
5 [$ j* ~/ {! M( q1 a: `' T

效果如下:

! p1 B' t) S; c

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

  • dbstop in file at location if expression% V6 u' Z# U1 P) @

比如有myprogram.m, 如下:

  • clear all;
  • close all
  • clc;
  • x = ones(1,10);
  • for n = 1:10
  •   x(n) = x(n) + 1;
  • end) s# ~$ }, n& `* T( W1 L
8 v2 P3 o7 h& }3 [, \( u

8 D' B' |! P* C* t

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

  • dbstop in myprogram at 6 if n>=4;
  • myprogram;
      q( s, }+ b: h! h# [5 q

' g# O* a3 M: i* z: {2 [* @& M
2 r" f) Y/ Y  I) E! u7 S

  这时有:

  • 6   x(n) = x(n) + 1;
  • K>>
  • Type dbquit to exit debug mode.
    - x" r: ^* N- Z2 F; ~0 W; [
+ y8 Y5 @- |4 E% N6 |

$ t7 R* E9 m. [4 \& r+ a, Y

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

  • dbstop in file at location   %在指定行设置断点! S* t* ~- b1 |# P) o2 X

' W4 k* |) F- D3 m5 R7 z+ x$ o
9 y" F- G7 T2 g- p. n

此时与F12等价。

所有dbstop,可配合return或者dbstop使用;3 M0 g, ]- N$ O1 Q, v3 B
  return:返回;6 y; |# p% d% W% J
  dbstop:停止
# \9 Y0 f, H1 z

' X) F! `2 m0 |% K7 y$ X

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

  • 清除所有M文件的所有断点
    ) z! |4 d* }- }  }" j% t5 t) a. J( s

在Command Windows输入:

  • dbclear all8 [8 E; {! q& e6 |
& |% Y9 M! z9 N) ~
0 f! e6 r# m/ w4 i
  • 清除文件名为mfile的文件的所有断点4 \- W( K; p2 G

在Command Windows输入:

  • dbclear all in mfile:
      ^( P( Q9 g, a7 R0 A$ N, K% x
. b; K* r3 x3 r9 Q. v
: J7 G( u3 h' a1 \/ t9 M) T  V3 O9 V
  • 其他dbstop相关(前文所述,已满足基本Debug,此处列出其他操作,不再展开介绍,供感兴趣的朋友阅读):
    ' H2 D% g8 ~0 |3 Y
(1)设置断点:

* dbstop in mfile:在文件名为mfile的M文件第一个可执行语句前设断点;  
# x6 a" r& g! J* dbstop in mfile at lineno:在mfile的第lineno行设断点;
# W- Q1 I) ^: k: X" ]3 t4 h/ }6 u5 G* dbstop in mfile at subfun:当程序执行到子程序subfun时,暂时中止执行,并设断点;. s4 e9 a& P4 e. I% k) j: y
* dbstop if error:遇到错误时,终止M文件运行,并停在错误行(不包括try...catch语句中检测到的的错误,不能在错误后重新开始运行);4 O4 f$ W# w9 t/ t$ s
* dbstop if all error:遇到任何类型错误均停止(包括try...catch语句中检测到的的错误);3 F' O2 y: v  I9 t4 t) A: {
* dbstop if warning:程序可恢复运行;+ g% |; r% l' T, @. e
* dbstop if caught error:当try...catch检测到运行时间错误是,停止M文件执行,可恢复运行;
# @$ A3 h( {& O( [3 q  M* dbstop if naninf 或 dbstop if infnan

(2)断点清除:

* dbclear all:清除所有M文件中的所有断点;5 D/ m9 P% ^4 Y, ?
* dbclear all in mfile:清除文件名为mfile的文件中的所有断点;
+ @" V8 d( r2 G# r$ s, n* dbclear in mfile:清除文件名为mfile中第一个可执行语句前的断点;' X8 g) ^5 G2 ^! s! t* C% C
* dbclear in mfile at lineno:
/ P( A& y" h, H# m- l* dbclear in mfile at subfun:6 \6 ?; a4 t$ _8 m; ~' K+ ^  j, n3 a2 f
* dbclear if error/warning/naninf/infnan:

(3)恢复运行:

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

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

* dbstep:执行下一个可执行语句;0 J- [1 b& k: g7 y: t
* dbstep nlines:执行下nlines行可执行语句;/ E) }3 s/ i9 ], H4 h
* dbstep in:执行下一行可执行语句,如有子函数,进入;
5 I( Z! u* _! t& g1 J* dbstep out:执行函数剩余部分,离开函数时停止;
3 B; h2 Y6 h0 D" O8 d- ^/ j2 Y. K* 注:这四种都返回调试模式,如遇断点,中止;

( Z: @- R5 Y# w

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-11-6 13:06 , Processed in 0.156250 second(s), 26 queries , Gzip On.

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

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

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