在matlab中保存调试状态

时间:2014-05-02 11:41:01

标签: matlab debugging savestate

我正在寻找一种方法,在停止调试时,在matlab会话中保存'

实施例

function funmain
a=1;
if a>1
  funsub(1)
end
funsub(2)
end

function funsub(c)
b = c + 1;
funsubsub(c)
end
function funsubsub(c)
c = c + 2; %Line with breakpoint
end

当我最终使用断点到达该行时,我可以轻松浏览所有工作区并查看所有函数调用的位置。

问题

我如何保持这种情况?


在调试需要很长时间才能运行的嵌套程序时,我常常会等待很长时间才能到达断点。有时候我只需要关闭matlab,或者想尝试一些东西然后再回到这一点,因此找到一种存储这种状态的方法是非常可取的。我在Windows Server 2008中工作,但更喜欢不需要安装任何软件的平台独立解决方案。

我尝试了什么

1。保存工作区中的所有变量:这有时会起作用,但我经常需要导航其他工作区

2。将所有变量保存在调用工作区中:这已经更好了,因为我可以再次运行最低功能,但可能仍然不够。对所有嵌套工作空间执行此操作不是很方便,导航已保存的工作空间可能更糟。

除了提到的不便之外,这也不允许我看到达到断点的确切路线。因此,我希望有更好的解决方案!


代码结构示例

代码看起来有点像

function fmain
fsub1()
fsub2()
fsub3()
end

function fsub1
fsubsub11
fsubsub12
...
fsubsub19
end

function fsub2
fsubsub21
fsubsub22
...
fsubsub29
end

function fsub3
fsubsub31
fsubsub32
...
fsubsub39
end

function fsubsub29
fsubsubsub291
fsubsubsub292% The break may occur in here
...
fsubsubsub299

休息当然可以在任何地方发生,通常我可以导航工作区及其上方的所有人。

2 个答案:

答案 0 :(得分:3)

点检查

您要实现的内容称为检查点代码。这对于运行很长时间的代码片段非常有用。我们来看一个非常简单的例子:

f=zeros(1e6,1);
for i=1:1e6
   f(i) = g(i) + i*2+5; % //do some stuff with f, not important for this example
end

在大多数机器上显然需要一段时间,所以如果它运行一半会很痛苦,然后你必须重新启动。那么让我们添加一个检查点!

f=zeros(1e6,1);
i=1; % //start at 1
% //unless there is a previous checkpoint, in which case skip all those iterations
if exist('checkpoint.mat')==2
  load('checkpoint.mat'); % //this will load f and i
end

while i<1e6+1
   f(i) = g(i) + i*2+5;
   i=i+1;

   if mod(i,1000)==0 % //let's save our state every 1000 iterations
      save('checkpoint.mat','f','i');
   end
end
delete('checkpoint.mat') % //make sure to remove it when we're done!

这允许您在处理过程中退出代码而不会丢失所有计算时间。决定检查点的时间和频率是性能和丢失时间之间的平衡!

示例代码实现

您的示例代码需要更新如下:

function fmain
sub1done=false; % //These really wouldn't be necessary if each function returns
sub2done=false; % //something, you could just check if the return exists
sub3done=false;
if exist('checkpoint_main.mat')==2, load('checkpoint_main.mat');end

if ~sub1done
    fprintf('Entering fsub1\n');
    fsub1()
    fprintf('Finished with fsub1\n');
    sub1done=true;
    save('checkpoint_main.mat');
end

if ~sub2done
    fprintf('Entering fsub2\n');
    fsub2()
    fprintf('Finished with fsub2\n');
    sub2done=true;
    save('checkpoint_main.mat');
end

if ~sub3done
    fprintf('Entering fsub3\n');
    fsub3()
    fprintf('Finished with fsub3\n');
    sub3done=true;
    save('checkpoint_main.mat');
end
delete('checkpoint_main.mat');
end



function fsub2
subsub21_done=false;subsub22_done=false;...subsub29_done=false;
if exist('checkpoint_fsub2')==2, load('checkpoint_fsub2');end
if ~subsub21_done
     fprintf('\tEntering fsubsub21\n');
     fsubsub21
     fprintf('\tFinished with fsubsub21\n');
     subsub21_done=true;
     save('checkpoint_fsub2.mat');
end


...
if ~subsub29_done
    fprintf('\tEntering fsubsub29\n');
    fsubsub29
    fprintf('\tFinished with fsubsub29\n');
    subsub29_done=true;
    save('checkpoint_fsub2.mat');
end
delete('checkpoint_fsub2.mat');
end


function fsubsub29
subsubsub291_done=false;...subsubsub299_done=false;
if exist('checkpoint_fsubsub29.mat')==2,load('checkpoint_fsubsub29.mat');end

if ~subsubsub291_done
    fprintf('\t\tEntering fsubsubsub291\n');
    fsubsubsub291
    fprintf('\t\tFinished with fsubsubsub291\n');
    subsubsub291_done=true;
    save('checkpoint_fsubsub29.mat');
end 

if ~subsubsub292_done
    fprintf('\t\tEntering fsubsubsub292\n');
    fsubsubsub292% The break may occur in here
    fprintf('\t\tFinished with fsubsubsub292\n')
    subsubsub292_done=true;
    save(checkpoint_fsubsub29.mat');
end
delete('checkpoint_fsubsub29.mat');
end

因此,在此结构中,如果您在程序被杀死后重新启动它,它将恢复到最后保存的检查点。因此,例如,如果程序在subsubsub291中死亡,程序将完全跳过fsub1,只加载结果。然后它会一直跳到subsub21一直到subsub29,在那里它会进入subsub29。然后它会跳过subsubsub291并输入292它停止的位置,加载了该工作空间和之前工作空间中的所有变量。因此,如果您将292退回到29,那么您将拥有与运行代码相同的工作空间。请注意,这也将打印出一个漂亮的树结构,因为它进入和退出函数以帮助调试执行顺序。

参考:

https://wiki.hpcc.msu.edu/pages/viewpage.action?pageId=14781653

答案 1 :(得分:0)

经过一番谷歌搜索后,我发现使用putvar(自定义函数来自http://au.mathworks.com/matlabcentral/fileexchange/27106-putvar--uigetvar)解决了这个问题。