Очистка после завершения выполнения функции

Панорама

Хорошая методика программирования должна убедиться, что вы покидаете свою среду программы в чистом состоянии, которое не вмешивается ни в какой другой код программы. Например, вы можете хотеть

  • Закройте любые файлы, которые вы открыли для импорта или экспорта.

  • Восстановите путь MATLAB®.

  • Заблокируйте или разблокируйте память, чтобы предотвратить или позволить стирать функцию MATLAB или файлы MEX.

  • Задержите свою рабочую папку к ее значению по умолчанию, если вы изменили ее.

  • Убедитесь, что глобальные и персистентные переменные находятся в правильном состоянии.

MATLAB обеспечивает onCleanup функция с этой целью. Эта функция, когда используется в рамках любой программы, устанавливает стандартную программу очистки для этой функции. Когда функция завершает работу, или обычно или в случае ошибки или Ctrl+C, MATLAB автоматически выполняет стандартную программу очистки.

Следующий оператор устанавливает стандартную программу очистки cleanupFun для в настоящее время под управлением программы:

cleanupObj = onCleanup(@cleanupFun);

Когда ваша программа выходит, MATLAB находит любые экземпляры onCleanup класс и выполняет указатели присоединенной функции. Процесс очистки функции генерации и активации включает следующие шаги:

  1. Запишите одну или несколько стандартных программ очистки для разрабатываемой программы. Примите на данный момент, что требуется только одна такая стандартная программа.

  2. Создайте указатель на функцию для стандартной программы очистки.

  3. В какой-то момент, обычно рано в вашем коде программы, вставьте вызов onCleanup функция, передавая указатель на функцию.

  4. Когда программа запущена, вызов onCleanup создает объект очистки, который содержит указатель на стандартную программу очистки, созданную на шаге 1.

  5. Когда программа заканчивается, MATLAB неявно очищает все объекты, которые являются локальными переменными. Это вызывает метод деструктора для каждого локального объекта в вашей программе, включая объект очистки, созданный на шаге 4.

  6. Метод деструктора для этого объекта вызывает эту стандартную программу, если это существует. Это выполняет задачи, должен был восстановить вашу среду программирования.

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

Если, по некоторым причинам, объект, возвращенный onCleanup сохраняется вне срока действия вашей программы, затем стандартная программа очистки, сопоставленная с тем объектом, не запущена, когда ваша функция завершает работу. Вместо этого это запустится каждый раз, когда объект уничтожается (например, путем очищения переменной объекта).

Ваша стандартная программа очистки никогда не должна использовать переменные, которые заданы за пределами той стандартной программы. Например, вложенная функция, показанная здесь слева, выполняется без ошибки, тогда как очень похожий на праве перестал работать с ошибкой, Undefined function or variable 'k'. Это следует из уверенности стандартной программы очистки в переменной k который задан за пределами вложенной стандартной программы очистки:

function testCleanup               function testCleanup
k = 3;                             k = 3;
myFun                              obj = onCleanup(@myFun);
    function myFun                     function myFun
    fprintf('k is %d\n', k)            fprintf('k is %d\n', k)
    end                                end
end                                end

Примеры очистки программы на выход

Пример 1 - закрывает открытые файлы на выходе

MATLAB закрывает файл с идентификатором fid когда функциональный openFileSafely завершает работу:

function openFileSafely(fileName)
fid = fopen(fileName, 'r');
c = onCleanup(@()fclose(fid));

s = fread(fid);
     .
     .
     .
end

Пример 2 - поддерживает выбранную папку

Этот пример сохраняет текущую папку ли functionThatMayError возвращает ошибку или нет:

function changeFolderSafely(fileName)
   currentFolder = pwd;
   c = onCleanup(@()cd(currentFolder));

   functionThatMayError;
   end   % c executes cd(currentFolder) here.

Пример 3 - закрывает фигуру и восстанавливает путь MATLAB

Этот пример расширяет путь MATLAB, чтобы включать файлы в toolbox\images папки, и затем отображает фигуру от одной из этих папок. После того, как фигура отображается, стандартная программа очистки restore_env закрывает фигуру и восстанавливает путь к его исходному состоянию.

function showImageOutsidePath(imageFile)
fig1 = figure;
imgpath = genpath([matlabroot '\toolbox\images']);

% Define the cleanup routine.
cleanupObj = onCleanup(@()restore_env(fig1, imgpath));

% Modify the path to gain access to the image file, 
% and display the image.
addpath(imgpath);
rgb = imread(imageFile);
fprintf('\n   Opening the figure %s\n', imageFile);
image(rgb);
pause(2);

   % This is the cleanup routine.
   function restore_env(fighandle, newpath)
   disp '   Closing the figure'
   close(fighandle);
   pause(2)
   
   disp '   Restoring the path'
   rmpath(newpath);
   end
end

Запустите функцию как показано сюда. Можно проверить, что путь был восстановлен путем сравнения длины пути до и после выполнения функции:

origLen = length(path);

showImageOutsidePath('greens.jpg')
   Opening the figure greens.jpg
   Closing the figure
   Restoring the path

currLen = length(path);
currLen == origLen
ans =
     1

Получение информации о стандартной программе очистки

В Примере 3 показанных выше, стандартная программа очистки и данные должны были вызвать его, содержатся в указателе на анонимную функцию:

@()restore_env(fig1, imgpath)

Детали того указателя затем содержатся в объекте, возвращенном onCleanup функция:

cleanupObj = onCleanup(@()restore_env(fig1, imgpath));

Можно получить доступ к этим деталям с помощью task свойство очистки возражает как показано здесь. (Измените showImageOutsidePath функция путем добавления следующего кода незадолго до строки с комментариями, которая говорит, “% This is the cleanup routine.”)

disp '   Displaying information from the function handle:'
task = cleanupObj.task;
fun = functions(task)
wsp = fun.workspace{2,1}
fprintf('\n');
pause(2);

Запустите модифицированную функцию, чтобы видеть выход functions команда и содержимое одного из workspace ячейки:

showImageOutsidePath('greens.jpg')

Opening the figure greens.jpg
Displaying information from the function handle:
fun = 
     function: '@()restore_env(fig1,imgpath)'
         type: 'anonymous'
         file: 'c:\work\g6.m'
    workspace: {2x1 cell}
wsp = 
     imageFile: 'greens.jpg'
          fig1: 1
       imgpath: [1x3957 char]
    cleanupObj: [1x1 onCleanup]
           rgb: [300x500x3 uint8]
          task: @()restore_env(fig1,imgpath)

Closing the figure
Restoring the path

Используя onCleanup По сравнению с попыткой/выгодой

Другой способ запустить стандартную программу очистки, когда функция завершает работу неожиданно, состоит в том, чтобы использовать try, catch оператор. Существуют ограничения к использованию этого метода как бы то ни было. Если стороны пользователя программа путем ввода Ctrl+C, MATLAB сразу выходит из try блокируйтесь, и стандартная программа очистки никогда не выполняется. Стандартная программа очистки также не запускается, когда вы обычно выходите из функции.

Следующая программа моется, если ошибка происходит, но не в ответ на Ctrl+C:

function cleanupByCatch
try
    pause(10);
catch
    disp('   Collecting information about the error')
    disp('   Executing cleanup tasks')
end

В отличие от try/catch оператор, onCleanup функция не только отвечает на нормальный выход из вашей программы и любой ошибки, которая может быть выдана, но также и к Ctrl+C. Этот следующий пример заменяет try/catch с onCleanup:

function cleanupByFunc
obj = onCleanup(@()...
    disp('   Executing cleanup tasks'));
pause(10);

onCleanup в Скриптах

onCleanup не работает в скриптах, как это делает в функциях. В функциях объект очистки хранится в функциональной рабочей области. Когда функция выходит, эта рабочая область очищена, таким образом выполнив связанную стандартную программу очистки. В скриптах объект очистки хранится в базовом рабочем пространстве (то есть, рабочая область, используемая в интерактивной работе, сделанной в командной строке). Поскольку выход из скрипта не оказывает влияния на базовое рабочее пространство, объект очистки не очищен, и стандартная программа, сопоставленная с тем объектом, не выполняется. Чтобы использовать этот тип механизма очистки в скрипте, необходимо было бы явным образом очистить объект от командной строки или другого скрипта, когда первый скрипт завершает работу.