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

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

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

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

    cfg = coder.config('lib'); % or 'dll' or 'exe'
    cfg.RuntimeChecks = true;
    codegen -config cfg myfunction
  • В MATLAB® Coder™ приложении в диалоговом окне параметров проекта на панели Debugging установите флажок Generate run-time error checks.

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

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

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

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

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

Ограничения

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

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

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

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

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

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

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

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

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

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

  • Сгенерированный код С++ выдает 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), что приводит к ошибке времени выполнения.

Запустите эти команды, чтобы сгенерировать исполняемый файл C с помощью измененных основных файлов. Назовите папку генерации кода 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)

См. также

| |

Похожие темы