メインコンテンツ

潜在的な相違メッセージ

潜在的な相違点のレポートを有効にすると、コード ジェネレーターは生成されたコードの動作と 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) のように動作します。MATLAB で、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 が可変サイズの行列の場合、コード ジェネレーターは一般的な MATLAB インデックス付けルールに従い、size(A(B))size(B) と等しいと仮定します。実行時に、AB が異なる方向をもつベクトルである場合、この仮定は正しくありません。したがって、実行時エラー チェックが有効な場合、エラーが発生する可能性があります。

このランタイム エラーを回避するには、次のいずれかの解決法を試してください。

  • A または B が実行時に固定サイズの行列である場合は、コード生成時にこの行列を固定サイズとして定義します。

  • 実行時に AB が両方ともベクトルである場合は、方向が一致していることを確認します。

  • コードが実行時に異なる方向のベクトルと行列を意図的に受け入れる場合は、ベクトル - ベクトル インデックス付けの明示的なチェックを含め、ベクトルを同じ方向に強制します。たとえば、関数 isvector を使用して、AB の両方がベクトルであるかどうかを判断し、ベクトルである場合は colon 演算子を使用して両方のベクトルを強制的に列ベクトルにします。

    ...
    if isvector(A) && isvector(B)
        Acol = A(:);
        Bcol = B(:);
        out = Acol(Bcol);
    else
        out = A(B);
    end
    ...

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

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

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

コード ジェネレーターは、MATLAB と同じベクトル - ベクトル インデックス付けルールを適用しようとします。コード生成時に A が可変サイズのベクトルである場合、コード ジェネレーターは A(B) の方向が A の方向と同じであると仮定します。ただし、次の両方の条件が true の場合は、この仮定は誤りであり、ランタイム エラーが発生します。

  • コード生成時に、A の方向が B の方向と一致しない。

  • 実行時に A がスカラーで、B がベクトルである。

このランタイム エラーを回避するには、次のいずれかの解決法を試してください。

  • A が実行時にスカラーである場合は、コード生成時に A をスカラーとして定義します。

  • AB がコード生成時にベクトルとして定義されている場合は、それらの方向が同じであることを確認します。

  • AB がコード生成時に方向が異なる可変サイズのベクトルである場合は、A が実行時にスカラーでないことを確認します。

  • AB がコード生成時に方向が異なる可変サイズのベクトルである場合は、B が実行時にベクトルでないことを確認します。

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

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

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

メモリの整合性チェックが有効になっている場合、ループ インデックスのオーバーフローが発生する可能性があることをコード ジェネレーターが検出すると、エラーが報告されます。ソフトウェアのエラー チェックは保守的です。ループ インデックスのオーバーフローを誤って報告する可能性があります。既定では、メモリの整合性チェックは MEX コードに対して有効化され、スタンドアロン C/C++ コードに対しては無効化されています。MEX 関数を使用した MATLAB コードの問題の確認 (MATLAB Coder)および実行時エラーを検出および報告するスタンドアロン C/C++ コードの生成 (MATLAB Coder)を参照してください。

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

オーバーフローを引き起こす可能性のあるループ条件回避方法
  • ループ インデックスが 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 以外の値でインクリメントまたはデクリメント

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

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

参考

トピック