3

私はこのCコードを持っています:

EaglePage* EaglePage_RealCopy(EaglePage *page)
{
    if(NULL == page) {
        return NULL;
    }

    switch(page->type) {

        case EagleDataTypeUnknown:
            EagleLogger_Log(EagleLoggerSeverityError, "Cannot page of Unknown type.");
            return NULL;

        case EagleDataTypeInteger:
            return EaglePage_RealCopyInt_(page);

        case EagleDataTypeVarchar:
            return EaglePage_RealCopyVarchar_(page);

        case EagleDataTypeFloat:
            return EaglePage_RealCopyFloat_(page);

    }
}

これをMac OS Xでclangを使用してコンパイルすると、スイッチがすべての「可能な」ブランチを処理し、(Javaのような)returnステートメントの欠落について警告しないことが理解されます。ただし、GCC 4.4.5 で同じコードを実行すると、常に返されないという警告が表示されます。

return ステートメントを挿入すると、「不可能な」シナリオをカバーしていないため、コード カバレッジが壊れてしまうため、面倒です。GCCがclang/javacのようにこれを処理する方法はありますか?

4

3 に答える 3

4

これは時々起こりますが、defaultラベルで簡単に修正できます。

switch(page->type) {

    case EagleDataTypeInteger:
        return EaglePage_RealCopyInt_(page);

    case EagleDataTypeVarchar:
        return EaglePage_RealCopyVarchar_(page);

    case EagleDataTypeFloat:
        return EaglePage_RealCopyFloat_(page);

    case EagleDataTypeUnknown:
    default:
        EagleLogger_Log(EagleLoggerSeverityError, "Cannot page of Unknown type.");
        return NULL;

}
于 2013-06-15T08:57:11.520 に答える
0

clang は単なるコンパイラではなく、バイトコード コンパイラと静的解析ツールのハイブリッドです。したがって、この特定のケースで clang からの警告が表示されない理由は、スイッチでカバーされていない値で関数を呼び出すことができないことを証明できるからです。

または、clang のバグである可能性があります。

この関数をコードに追加して、それが呼び出されることを確認し、何が起こるかを確認してください。

void BogusEaglePage_Call(void) {
  EaglePage *bp, *br;
  bp = malloc (sizeof (*bp));
  if (bp) {
    bp->type = (EagleDataTypeInteger | EagleDataTypeVarchar | EagleDataTypeFloat | EagleDataTypeUnknown) << 2;
    br = EaglePage_RealCopy(bp);
  }
}

それでも clang で警告が表示されない場合は、不具合を報告することをお勧めします。

于 2013-06-15T19:22:37.167 に答える
0

可能な値が 4 つしかないことを知るための情報をコンパイラーに与えていません。ケースとすべてのパスが処理されます (スイッチの後のコードは到達不能としてフラグが立てられます)。コンパイラがそれを実行できるかどうかは、そのブランドとバージョンの特定の機能であるコンパイラに関係しています。

単一のリターンポイントを持っていても、あなたがやろうとしていることで何も得られません.このコードを介して5つのパスを検証する必要があります. コンパイラは常にシステム レベルを監視しているわけではなく、常にシステム レベルを監視しているわけではありませんが、関数レベルにしか注目できない場合もあります。llvm ツールは、個別にコンパイルされたソース ファイルを使用してプロジェクト全体を簡単に最適化できます。gcc では、そのためにすべてを 1 つの大きなファイル (インクルード付き) で必要とします。

コードを作成すると、コンパイラはコードを介して 5 番目のパスを適切に生成します。これは、コードが指示していることであり、コンパイラにバグがない限り実行することです。コンパイラに何か他のことをさせたい場合は、ソースコードを変更してコンパイラに何か他のことをするように伝えます(または、あなたが示した以上のことをコンパイラに示します。ここにコードがある場合、このコードでコンパイルされていることがわかりません別の話、または上で示したように、このコードで範囲制限をコンパイラに示した場合、その範囲に制限する機会を持つことができます)。

于 2013-06-15T19:44:23.603 に答える