Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

潜在的な相違メッセージ

潜在的な相違点のレポートを有効にすると、コード ジェネレーターは生成されたコードの動作と MATLAB® コードの動作の潜在的な相違点をレポートします。スタンドアロン コードを生成する前に潜在的な相違を確認し、解決すると、生成されたコードでエラーおよび正しくない回答を回避できます。

潜在的な相違メッセージの一部を次に示します。

自動次元の非互換性

生成されたコードでは、動作する対象の次元は自動的に
選択され、MATLAB とは異なっている場合があります。
使用する次元を明示的に定数値として指定することを
検討してください。

この制限は使用する次元 (動作する対象の次元) を入力として取得する関数に適用されます。MATLAB およびコード生成で、使用する次元を指定しないと、関数が次元を選択します。MATLAB では、関数は、サイズが 1 ではない最初の次元を選択します。コード生成では、関数は、可変サイズを持つまたは 1 以外の固定サイズを持つ最初の次元を選択します。使用する次元が可変サイズで、実行時に 1 になる場合、使用する次元は MATLAB の使用する次元と異なります。したがって、実行時エラー チェックが有効な場合、エラーが発生する可能性があります。

たとえば、X は、次元が 1x:3x:5 の可変サイズ行列であるとします。生成されたコードで、sum(X)sum(X,2) のように動作します。MATLAB で、sum(X) は、size(X,2) が 1 でない場合、sum(X,2) のように動作します。size(X,2) が 1 の場合は、sum(X)sum(X,3) のように動作します。

この問題を回避するには、使用する次元を定数値で明示的に指定します。例: sum(X,2)

mtimes の動的なスカラー拡張なし

生成されたコードでは、一般的な行列の乗算が行われます。
可変サイズの行列のオペランドが実行時にスカラーになる場合
でも、次元は一致しなければなりません。スカラー乗算への
自動的な切り替えはありません。

乗算 A*B について考えます。コード ジェネレーターは、A がスカラーで B が行列であることを認識すると、スカラー行列乗算のコードを生成します。ただし、コード ジェネレーターは、AB が可変サイズの行列であると認識すると、一般的な行列乗算のコードを生成します。実行時に、A がスカラーであることが判明しても、生成されたコードはその動作を変更しません。したがって、実行時エラー チェックが有効な場合、サイズの不一致エラーが発生する可能性があります。

行列 - 行列インデックス付け

行列による行列のインデックス付け matrix1(matrix2) において、
コード ジェネレーターは結果のサイズが matrix2 と同じになると
仮定しました。matrix1 と matrix2 が実行時にベクトルである
場合、両者の向きは一致しなければなりません。

行列 - 行列インデックス付けでは、1 つの行列を使用して別の行列にインデックスを付けます。MATLAB で、行列 - 行列インデックス付けの一般的なルールは、結果のサイズと方向がインデックス行列のサイズと方向に一致するということです。たとえば、AB が行列の場合、size(A(B))size(B) と等しくなります。AB がベクトルの場合、MATLAB では特別なルールが適用されます。特別なベクトル - ベクトル インデックス付けルールは、結果の方向がデータ行列の方向になることです。たとえば、A が 1 行 5 列で、B が 3 行 1 列の場合、A(B) は 1 行 3 列になります。

コード ジェネレーターは、MATLAB と同じ行列 - 行列インデックス付けルールを適用します。AB が可変サイズ行列の場合、行列 - 行列インデックス付けルールを適用するために、コード ジェネレーターは size(A(B))size(B) と等しいと仮定します。実行時に、AB がベクトルになり、異なる方向を持つ場合、この仮定は正しくありません。したがって、実行時エラー チェックが有効な場合、エラーが発生する可能性があります。

この問題を回避するには、インデックスにコロン演算子を使用して、データを強制的にベクトルにします。たとえば、コードが意図的に実行時にベクトルと正則行列を切り替えるものであるとします。ベクトル - ベクトル インデックス付けを明示的に次のようにチェックすることができます。

...
if isvector(A) && isvector(B)
    C = A(:);
    D = C(B(:));
else
    D = A(B);
end
...

最初の分岐のインデックス付けが、CB(:) をコンパイル時のベクトルとして指定しています。したがって、コード ジェネレーターは、1 つのベクトルを別のベクトルでインデックス付けするインデックス付けルールを適用します。結果の方向はデータ ベクトル C の方向となります。

ベクトル - ベクトル インデックス付け

ベクトルによるベクトルのインデックス付け vector1(vector2) において、
コード ジェネレーターは結果の向きが vector1 と同じになると仮定しました。
vector1 が実行時にスカラーである場合、vector2 の向きは vector1 と
一致しなければなりません。

MATLAB で、ベクトル - ベクトル インデックス付けの特別なルールは、結果の方向がデータ ベクトルの方向であるということです。たとえば、A が 1 行 5 列で、B が 3 行 1 列である場合、A(B) は 1 行 3 列になります。ただし、データ ベクトル A がスカラーの場合、A(B) の方向はインデックス ベクトル B の方向になります。

コード ジェネレーターは、MATLAB と同じベクトル - ベクトル インデックス付けルールを適用します。AB が可変サイズ ベクトルである場合、インデックス付けルールを適用するには、コード ジェネレーターは B の方向が A の方向と一致すると仮定します。実行時に、A がスカラーで、AB の方向が一致しない場合、この仮定は正しくありません。したがって、実行時エラー チェックが有効な場合、実行時エラーが発生する可能性があります。

この問題を回避するには、ベクトルの方向を一致させます。または、行と列を指定して単一要素にインデックス付けします。例: A(row, column)

ループ インデックスのオーバーフロー

生成されたコードでは、ループの最後の反復でループ インデックスが
オーバーフローしないと仮定されます。ループ インデックスがオーバー
フローすると、無限ループが発生する可能性があります。

for ループの終了値がループ インデックスのデータ型の最大値または最小値と等しいか近いと仮定します。生成コードでは、ループ インデックスの最後のインクリメントまたはデクリメントによって、インデックス変数のオーバーフローが発生する可能性があります。インデックスのオーバーフローの結果、無限ループが発生する可能性があります。

メモリの整合性チェックが有効になっている場合、ループ インデックスのオーバーフローが発生する可能性があることをコード ジェネレーターが検出すると、エラーが報告されます。ソフトウェアのエラー チェックは保守的です。ループ インデックスのオーバーフローを誤って報告する可能性があります。既定では、メモリの整合性チェックは MEX コードに対して有効化され、スタンドアロン C/C++ コードに対しては無効化されています。MATLAB で MEX 関数をテストする理由およびGenerate Standalone C/C++ Code That Detects and Reports Run-Time Errorsを参照してください。

ループ インデックスのオーバーフローを回避するには、次の表の回避方法を使用してください。

オーバーフローを引き起こす可能性のあるループ条件回避方法
  • ループ インデックスが 1 ずつインクリメント

  • 終了値が整数データ型の最大値

ループがあらゆる整数データ型に対応する必要がない場合、終了値が整数データ型の最大値と等しくならないようにループを書き換えます。たとえば、

N=intmax('int16')
for k=N-10:N
次に置き換えます。
for k=1:10

  • ループ インデックスが 1 ずつデクリメント

  • 終了値が整数データ型の最小値

ループがあらゆる整数データ型に対応する必要がない場合、終了値が整数データ型の最小値と等しくならないようにループを書き換えます。たとえば、

N=intmin('int32')
for k=N+10:-1:N
次に置き換えます。
for k=10:-1:1

  • ループ インデックスが 1 ずつインクリメントまたはデクリメント

  • 開始値が整数データ型の最小値または最大値

  • 終了値が整数データ型の最大値または最小値

ループがあらゆる整数データ型に対応しなければならない場合は、ループの開始値、ステップ、および終了値の型をより大きな整数または double の値にキャストします。たとえば、次のコードを書き換えます。

M= intmin('int16');
N= intmax('int16');
for k=M:N
	% Loop body
end
以下のように書き換えます。
M= intmin('int16');
N= intmax('int16');
for k=int32(M):int32(N)
	% Loop body
end

  • ループ インデックスが 1 以外の値でインクリメントまたはデクリメント

  • 最後のループ反復において、ループ インデックスが終了値と等しくならない

ループを書き直し、最後のループ反復におけるループ インデックスが終了値と等しくなるようにします。

関連するトピック