exponenta event banner

Создание автономного кода C/C + +, обнаруживающего ошибки выполнения и сообщающего об этих ошибках

Во время разработки перед созданием кода C/C + + рекомендуется протестировать сгенерированный код, запустив версию алгоритма MEX. Однако некоторые ошибки возникают только на целевом оборудовании. Чтобы обнаружить эти ошибки, создайте автономные библиотеки и исполняемые файлы, которые обнаруживают ошибки времени выполнения и сообщают о них, например, индексирование массива вне границ.

По умолчанию обнаружение ошибок во время выполнения отключено для автономных библиотек и исполняемых файлов. Чтобы включить обнаружение ошибок во время выполнения и создание отчетов для автономных библиотек и исполняемых файлов:

  • В командной строке используйте свойство конфигурации кода RuntimeChecks.

    cfg = coder.config('lib'); % or 'dll' or 'exe'
    cfg.RuntimeChecks = true;
    codegen -config cfg myfunction
  • В приложении MATLAB ® Coder™ в диалоговом окне параметров проекта на панели Отладка установите флажок Генерировать ошибки во время выполнения.

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

Сгенерированный код C по сравнению с сгенерированным кодом C++

Если целевым языком является C, созданный код использует fprintf для записи сообщений об ошибках в stderr. Затем код использует abort для завершения работы приложения. Если fprintf и abort недоступны, их необходимо предоставить. abort функция резко завершает программу. Если система поддерживает сигналы, можно перехватить сигнал прекращения (SIGABRT), чтобы можно было управлять завершением программы.

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

Однако для проверки ошибок во время выполнения внутри параллельных областей (либо parfor петли или автоматически параллелизованные for петли), сгенерированный код C++ не вызывает исключения. В таких ситуациях генерируемый код использует fprintf для записи сообщений об ошибках в stderr, а затем использует abort для завершения работы приложения. Дополнительные сведения об автоматическом распараллеливании см. в разделе Автоматическое распараллеливание для циклов в сгенерированном коде.

Ограничения

Обнаружение ошибок во время выполнения и создание отчетов в автономном коде имеют следующие ограничения:

  • Сообщения об ошибках только на английском языке.

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

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

  • Если генерируемый код C завершается, программное обеспечение обнаружения ошибок и создания отчетов не освобождает ресурсы, такие как выделенная память. Созданный код C++ не имеет этого ограничения. Если генерируемый код C++ завершается, выделенная память и другие ресурсы освобождаются.

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

  • В автономном коде, если вызывается с более чем 1 аргументом, функция assert не сообщает об ошибке и не завершает выполнение. Если вызывается с одним аргументом, например, assert(cond), если cond не является константой true значение, сообщает об ошибке и завершает выполнение.

Пример: Сравнение сгенерированного кода C и C++, включающего проверки времени выполнения

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

  • Сгенерированный код C использует fprintf для записи сообщения об ошибке в stderr. Затем код использует abort для завершения работы приложения.

  • Сгенерированный код C++ выдает std::runtime_error исключение для этой ошибки времени выполнения. В основной функции C++, которую вы записываете для вызова сгенерированной функции, вы ловите и обрабатываете это исключение с помощью try-catch блок.

Определение функции MATLAB

Определение функции MATLAB errorCheckExample в отдельном файле. Эта функция вычисляет квадратный корень входного аргумента:

type errorCheckExample
function y = errorCheckExample(x)
y = sqrt(x);
end

Создание библиотеки C и исполняемого файла

Создание динамически связанной библиотеки C для errorCheckExample который принимает двойной скалярный ввод. Использовать объект конфигурации кода с RuntimeChecks параметр имеет значение true. Также используйте -d возможность именовать папку создания кода как codegen_c_dll.

cfg = coder.config('dll');
cfg.RuntimeChecks = true;
codegen -config cfg errorCheckExample -args 1 -d codegan_c_dll -report
Code generation successful: To view the report, open('codegan_c_dll/html/report.mldatx').

Откройте отчет о создании кода и проверьте файл. errorCheckExample.c. Функция C, созданная для функции MATLAB, имеет подпись double errorCheckExample(double x). Чтобы вычислить квадратный корень, errorCheckExample вызывает sqrt библиотечная функция, которая вычисляет только вещественные квадратные корни. Итак, errorCheckExample может принимать только положительные входные данные. Для отрицательных входных данных errorCheckExample вызывает созданную функцию утилиты rtErrorWithMessageID который использует fprintf для записи сообщения об ошибке в stderr а затем использует abort для завершения работы приложения.

static void rtErrorWithMessageID(const int b, const char *c,
                                 const char *aFcnName, int aLineNum)
{
  fprintf(stderr,
          "Domain error. To compute complex results from real x, use "
          "\'%.*s(complex(x))\'.",
          b, c);
  fprintf(stderr, "\n");
  fprintf(stderr, "Error in %s (line %d)", aFcnName, aLineNum);
  fprintf(stderr, "\n");
  fflush(stderr);
  abort();
}

При создании кода библиотеки генератор кода также создает примеры основных файлов. main.h и main.c в examples подпапка папки построения. Поддерживающие файлы C main_runtime_check.h и main_runtime_check.c являются измененными версиями этих файлов примеров. Измененный main функция вызывает errorCheckExample(-4), что приводит к ошибке времени выполнения.

Выполните эти команды для создания исполняемого файла Си с использованием измененных основных файлов. Имя папки создания кода codegen_c_exe. Имя исполняемого файла errorCheckExample_c с помощью -o опция с codegen команда.

cfg = coder.config('exe');
cfg.RuntimeChecks = true;
cfg.CustomSource = 'main_runtime_check.c';
cfg.CustomInclude = pwd;

codegen -config cfg main_runtime_check.c main_runtime_check.h errorCheckExample -args 1 -o errorCheckExample_c -d codegen_c_exe
Code generation successful.

Запустите созданный исполняемый файл. Обратите внимание, что оно печатает сообщение об ошибке, которое жестко закодировано в функции утилиты rtErrorWithMessageID.

if isunix
    system('./errorCheckExample_c');
elseif ispc
    system('errorCheckExample_c.exe');
else
    disp('Platform is not supported');
end
Domain error. To compute complex results from real x, use 'sqrt(complex(x))'.
Error in sqrt (line 13)
./errorCheckExample_c: Aborted

Создание библиотеки C++ и исполняемого файла

Создание динамически связанной библиотеки C++ для errorCheckExample который принимает скалярный двойной ввод. Использовать объект конфигурации кода с RuntimeChecks параметр имеет значение true. Также используйте -d возможность именовать папку создания кода как codegen_cpp_dll.

cfg = coder.config('dll');
cfg.RuntimeChecks = true;
codegen -config cfg -lang:c++ errorCheckExample -args 1 -d codegen_cpp_dll -report
Code generation successful: To view the report, open('codegen_cpp_dll/html/report.mldatx').

Откройте отчет о создании кода и проверьте файл. errorCheckExample.cpp. Аналогично функции C, созданной в предыдущем разделе, errorCheckExample может принимать только положительные входные данные. Для отрицательных входных данных errorCheckExample вызывает функцию утилиты rtErrorWithMessageID. Но в этом случае функция утилиты бросает std:runtime_error исключение, которое можно уловить и обработать в написанном вручную main функция.

static void rtErrorWithMessageID(const char *b, const char *aFcnName,
                                 int aLineNum)
{
  std::stringstream outStream;
  ((outStream << "Domain error. To compute complex results from real x, use \'")
   << b)
      << "(complex(x))\'.";
  outStream << "\n";
  ((((outStream << "Error in ") << aFcnName) << " (line ") << aLineNum) << ")";
  throw std::runtime_error(outStream.str());
}

При создании кода библиотеки генератор кода также создает примеры основных файлов. main.h и main.c в examples подпапка папки построения. Поддерживающие файлы C++ main_runtime_check.hpp и main_runtime_check.cpp являются измененными версиями этих файлов примеров. Измененный main() функция вызывает errorCheckExample(-4) внутри try-catch блок. Блок перехватывает исключение и печатает измененное сообщение, предваряя строку "Caught excaption: " в сообщение, которое содержит обнаруженное исключение.

Выполните эти команды для создания исполняемого файла C++ с использованием измененных основных файлов. Имя папки создания кода codegen_cpp_exe. Имя исполняемого файла errorCheckExample_cpp.

cfg = coder.config('exe');
cfg.RuntimeChecks = true;
cfg.CustomSource = 'main_runtime_check.cpp';
cfg.CustomInclude = pwd;

codegen -config cfg -lang:c++ main_runtime_check.cpp main_runtime_check.hpp errorCheckExample -args 1 -o errorCheckExample_cpp -d codegen_cpp_exe
Code generation successful.

Запустите созданный исполняемый файл. Обратите внимание, что оно печатает измененное сообщение об ошибке.

if isunix
    system('./errorCheckExample_cpp');
elseif ispc
    system('errorCheckExample_cpp.exe');
else
    disp('Platform is not supported');
end
Caught exception: Domain error. To compute complex results from real x, use 'sqrt(complex(x))'.
Error in sqrt (line 13)

См. также

| |

Связанные темы