3

このコードは、3 つの misrac エラーを報告します。

  1. 不適切なマクロ展開
  2. 関数のようなマクロ定義
  3. 括弧なしのマクロ パラメータ

元のコードは次のとおりです。

#define Wait(a, b)                         \
if (READ(b+0x1U))                          \
{                                          \
    while ((a & Write(b)))                 \
    {                                      \
        /* Do nothing - Busy wait */       \
    }                                      \
}

Here READ(b) is a macro and Write(b) is a function with no Misra C error.

エラーを削除するために変更しようとしています

#define Wait(a, b)                                                 \
if ((uint32_t)0U != READ((b)+0x1U))                                \
{                                                                  \
    while ((uint32_t)0U != ((uint32_t)(a) & Write((uint32_t)(b)))) \
    {                                                              \
        /* Do nothing - Busy wait */                               \
    }                                                              \
}

しかし、まだ最初の 2 つのエラーが発生しています。これらの Misra C エラーを取り除くために何をする必要がありますか。

4

2 に答える 2

6

1.不適切なマクロ展開

これは、マクロを適切にカプセル化していないためです。これを修正するには、コードを次のように変更する必要があります。

#define Wait(a, b)                         \
                                           \
do {                                       \
  if (READ(b+0x1U))                        \
  {                                        \
    while ((a & Write(b)))                 \
    {                                      \
        /* Do nothing - Busy wait */       \
    }                                      \
  }                                        \
} while (0);

(しかし、もちろん、コードの残りの部分が MISRA-C に従っており、常に{}すべてifの , fororwhileステートメントの後に使用する場合、これは無意味な演習です。)


2.関数的なマクロ定義

関数のようなマクロを使用しています。これは MISRA-C では許可されていません。マクロを関数として書き直します。

ただし、ルール 19.7 は推奨事項であるため、理論上は偏差を上げずに無視できます。しかし、この場合、そうする理由はありません。これが関数ではなくマクロである必要がある理由はありません。


3.括弧なしのマクロパラメータ

ご想像のとおり、これはすべてのマクロ パラメーターが潜在的なサブ式であることに関係しています。誰かがあなたのマクロを として呼び出すとしますWait(x+y, z)。マクロが に展開されるため、コードは while ループに遭遇するとクラッシュして焼き付きます。while(x+y & Write(b))これは と同じですwhile(x + (y & Write(b)) )

これを解決するには、2 番目の例のように、 and のすべてのインスタンスを括弧で囲みaますb


このコードは、3 つの misrac エラーを報告します。

Klockwork にバグを報告する必要があります。ツールが正しく機能していません。また、次のことも検出されているはずです。

  • if (READ(b+0x1U))規則 13.2 に違反します。MISRA 準拠のコードは次のようになります。

    if (READ(b+0x1U) != 0u)
    
  • while ((a & Write(b)))規則 13.2 に違反します。MISRA 準拠のコードは次のようになります。

    while ( (a & Write(b)) != 0u )
    

MISRA 以外の懸念事項:

  • (uint32_t)0Uは、より読みやすい形式である0ULまたはのように記述することをお勧めします。0ul
  • 率直に言って、このコードは最初から悪いものでした。このまま MISRA 準拠にしようとすると、完全に判読不能な混乱になってしまいます。代わりに最初から書き直します。

    void Wait (uint32_t a, uint32 b)
    {
      if( READ(b + 0x1u) != 0u )           /* comment here, explaining the code */
      {
        while ( (a & Write(b)) != 0u )     /* comment here, explaining the code */
        {
          ;                                /* Do nothing - busy wait */
        }
      }
    }
    
于 2013-12-10T12:37:51.233 に答える
3

マクロが展開できるもののリストがあり、if ブロックはそれらの 1 つではありません。これは、else 句の添付について混乱を招く可能性があるためだと思います。 詳細については、こちらをご覧ください。 この構成を使用できます。

#define MACRO(X)    \
do {                \
    body here       \
} while (0)

できる限り、関数のようなマクロではなく、関数を使用する必要があります。READ が何に展開されるかを知らなければ、この場合にそれが可能かどうかはわかりません。それが、それに関する警告を取り除く唯一の方法です。

3 つ目は、すでにわかっていることです。括弧を本体の前後aに配置する必要があります。bここでの考え方は、マクロのようなコードがx*2あり、誰かが3+1括弧なしで x として渡すと、ほぼ確実に意図された 8 である3+1*2ではなく、5 になるということです。(3+1)*2

あなたのコードについて私が言わなければならない唯一のことは、あなたが本当に&そこに欲しいの&&ですか?

于 2013-12-09T19:24:54.747 に答える