Сохраните состояние отладки в Matlab

Я ищу способ сохранить 'все' в сеансе 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

Когда я, наконец, дохожу до строки с точкой останова, я могу легко перемещаться по всем рабочим пространствам и видеть, где выполняются все вызовы функций.

Вопрос

Как я могу сохранить эту ситуацию?


При отладке вложенных программ, выполнение которых занимает много времени, я часто обнаруживаю, что подолгу жду достижения точки останова. А иногда мне просто нужно закрыть матлаб, или я хочу попробовать что-то, а потом вернуться к этому моменту, поэтому найти способ сохранить это состояние было бы весьма желательно. Я работаю в 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

Разрыв, конечно, может произойти где угодно, и обычно я мог бы перемещаться по рабочему пространству и всему, что над ним.


person Dennis Jaheruddin    schedule 02.05.2014    source источник
comment
@Acorbe Я работаю на Windows Server 2008,   -  person Dennis Jaheruddin    schedule 02.05.2014
comment
Я понимаю. Насколько я понимаю ваш вопрос, вы хотите иметь опцию restart для отладки. Можно сбросить весь процесс Matlab в файл, чтобы перезагрузить его позже. Это в принципе возможно в Linux через crtools. А вот про окна не знаю.   -  person Acorbe    schedule 02.05.2014
comment
@Acorbe Что касается Windows, я считаю, что сохранение состояния невозможно. — надежный источник в виде Раймонда Чена... Так что этот метод может быть вне окна ... Я читал (не могу вспомнить, где) о возможности использования виртуальной машины, на которой запущен другой экземпляр Windows, для сохранения состояния, но я не видел доказательств того, что это действительно работает.   -  person RTL    schedule 02.05.2014
comment
В вопросе добавлено следующее: я работаю в Windows Server 2008, но предпочел бы независимое от платформы решение, не требующее установки какого-либо программного обеспечения.   -  person Dennis Jaheruddin    schedule 02.05.2014
comment
Похоже, вам нужны модульные тесты. Большинство распространенных ошибок на самом деле не зависят от специфики ввода (т. е. данные могут быть фиктивными, но они все равно не сломаются при ошибке).   -  person Bernhard    schedule 04.05.2017


Ответы (2)


контрольно-пропускной пункт

То, что вы хотите реализовать, известно как код контрольных точек. Это может быть очень полезно для фрагментов кода, которые выполняются в течение очень долгого времени. Возьмем очень простой пример:

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

person Raab70    schedule 02.05.2014
comment
Я думаю, что это просто сохранение некоторых переменных. (Похоже на пункт 1 того, что я пробовал). Это может быть удобно для запуска кода, но не сохранит состояние отладки и не будет иметь дело с вложенными функциями. -- Спасибо за внимание, но я считаю, что это не ответ на правильный вопрос. - person Dennis Jaheruddin; 02.05.2014
comment
@DennisJaheruddin, на самом деле это не отвечает на ваш вопрос, но может быть обходным путем. Вместо сохранения состояния отладки он позволяет быстрее воссоздать это состояние отладки. - person A. Donda; 02.05.2014
comment
Точно, я понимаю, что это сохранение переменных, но это позволяет вам возобновить работу с того места, где вы остановились. Затем вы можете поставить точку останова после оператора загрузки, и вы возобновите свое состояние, не дожидаясь вычислений. Почему за это проголосовали? Если вы не уверены, как это решает вашу конкретную проблему, я могу привести пример того, как это будет работать при вызове функций. - person Raab70; 02.05.2014
comment
Мне это тоже не кажется плохим. Его легко реализовать, достигается надежность, и благодаря правильной стратегии экономии можно быстро достичь точки сбоя. - person Acorbe; 02.05.2014
comment
@Acorbe Возможно, проблема в том, что я не вижу, как это реализовать. Я включил образец структуры кода выше, обратите внимание, что на практике определенная функция может вызываться несколько раз на разных уровнях. - person Dennis Jaheruddin; 05.05.2014
comment
@DennisJaheruddin Я добавил пример реализации в структуру вашего кода. Также обратите внимание, что вы можете сделать контрольную точку в 292, как описано в верхнем разделе. - person Raab70; 05.05.2014

Немного погуглив, я обнаружил, что с помощью putvar (пользовательская функция отсюда: http://au.mathworks.com/matlabcentral/fileexchange/27106-putvar--uigetvar) решил эту проблему.

person algotrific    schedule 04.05.2017