CWE Rule 561
説明
ルールの説明
The software contains dead code, which can never be executed.
Polyspace 実装
ルール チェッカーは以下の問題をチェックします。
デッド コード
呼び出されていない静的関数
到達不能コード
例
この問題は、常に true または false になる条件が原因でコードのブロックに到達できない場合に発生します。この欠陥は以下を除外します。
Code deactivated by constant false condition:#if 0またはif(0)などのコンパイル時の定数を使用する命令をチェックする。Unreachable code:goto、break、returnなどのコントロール エスケープ後のコードをチェックする。Useless if: ステートメントが常に true であるかどうかをチェックする。
デッド コードは開発時間、メモリ、および実行サイクルを浪費します。開発者は実行されないコードを保守しなければなりません。実行されない命令でも保存およびキャッシュされる必要があります。
デッド コードは多くの場合、使用されることのないレガシ コードを表します。デッド コードを定期的にクリーン アップすると、将来の保守の負担が減ります。
修正方法は欠陥の根本原因によって異なります。たとえば、同じ実行パスで 2 回チェックされるエラー状態が根本原因で、2 回目のチェックが冗長であるため、対応するブロックがデッド コードになっている可能性があります。
多くの場合、結果の詳細 (または Polyspace as You Code のソース コード ツールヒント) には欠陥につながる一連のイベントが表示されます。そのシーケンス内のどのイベントについても修正を実装できます。結果の詳細にイベント履歴が表示されない場合は、ソース コード内で右クリック オプションを使用して、欠陥に関連する変数のこれまでの参照を検索し、関連するイベントを検出できます。Polyspace デスクトップ ユーザー インターフェイスでの Bug Finder の結果の解釈またはPolyspace Access Web インターフェイスでの Bug Finder の結果の解釈 (Polyspace Access)も参照してください。
以下の修正例を参照してください。
isinf や isnan などの関数の使用でデッド コードが表示された場合、非有限値を考慮に入れる解析モードを有効にします。詳細は、非有限の浮動小数点を検討 (-allow-non-finite-floats) を参照してください。
問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。
Polyspace ユーザー インターフェイスでのバグ修正または正当化による結果への対処 (Polyspace ユーザー インターフェイスで結果をレビューする場合)。
Polyspace Access でのバグ修正または正当化による結果への対処 (Polyspace Access) (Web ブラウザーで結果をレビューする場合)。
コードへの注釈付けと既知の結果または許容可能な結果の非表示 (IDE で結果をレビューする場合)
#include <stdio.h>
int Return_From_Table(int ch){
int table[5];
/* Create a table */
for(int i=0;i<=4;i++){
table[i]=i^2+i+1;
}
if(table[ch]>100){ //Noncompliant
return 0;
}
return table[ch];
}
配列 table 内の最大値は 4^2+4+1=21 であるため、テスト式 table[ch]>100 は常に false として評価されます。if ステートメント内の return 0 は実行されません。
1 つの修正方法として、if 条件をコードから削除することができます。
#include <stdio.h>
int Return_From_Table(int ch){
int table[5];
/* Create a table */
for(int i=0;i<=4;i++){
table[i]=i^2+i+1;
}
return table[ch];
}
typedef enum _suit {UNKNOWN_SUIT, SPADES, HEARTS, DIAMONDS, CLUBS} suit;
suit nextcard(void);
void do_something(suit s);
void bridge(void)
{
suit card = nextcard();
if ((card < SPADES) || (card > CLUBS))
card = UNKNOWN_SUIT;
if (card > 7) { //Noncompliant
do_something(card);
}
}
suit 型は 5 つのオプションで列挙されます。ただし、条件式 card > 7 は card の最大値が 5 であるため常に false と評価されます。if ステートメント内の内容は実行されません。
1 つの修正方法としてコードの if 条件を変更することができます。この修正では、7 は HEART に変更され、card 型に直接関連付けます。
typedef enum _suit {UNKNOWN_SUIT, SPADES, HEARTS, DIAMONDS, CLUBS} suit;
suit nextcard(void);
void do_something(suit s);
void bridge(void)
{
suit card = nextcard();
if ((card < SPADES) || (card > CLUBS))
card = UNKNOWN_SUIT;
if (card > HEARTS) {
do_something(card);
}
}
この問題は、static 関数が、それが定義されたファイル内で呼び出されなかった場合に発生します。
呼び出されていない関数は多くの場合、レガシ コードに起因し、不要な保守の原因になります。
呼び出されることを意図していない関数は削除します。デバッグ専用の関数の場合は、デバッグ マクロで関数定義をラップします。
以下の修正例を参照してください。
問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。
Polyspace ユーザー インターフェイスでのバグ修正または正当化による結果への対処 (Polyspace ユーザー インターフェイスで結果をレビューする場合)。
Polyspace Access でのバグ修正または正当化による結果への対処 (Polyspace Access) (Web ブラウザーで結果をレビューする場合)。
コードへの注釈付けと既知の結果または許容可能な結果の非表示 (IDE で結果をレビューする場合)
次のコードをファイル Initialize_Value.c に保存します。
#include <stdlib.h>
#include <stdio.h>
static int Initialize(void) //Noncompliant
/* Defect: Function not called */
{
int input;
printf("Enter an integer:");
scanf("%d",&input);
return(input);
}
void main()
{
int num;
num=0;
printf("The value of num is %d",num);
}static 関数 Initialize は、ファイル Initialize_Value.c 内で呼び出されていません。
1 つの修正方法として、Initialize をファイル Initialize_Value.c 内で少なくとも一度呼び出すことができます。
#include <stdlib.h>
#include <stdio.h>
static int Initialize(void)
{
int input;
printf("Enter an integer:");
scanf("%d",&input);
return(input);
}
void main()
{
int num;
/* Fix: Call static function Initialize */
num=Initialize();
printf("The value of num is %d",num);
}この問題は、制御フロー内の break が原因で、その先のコードのセクションに到達できなかった場合に発生します。
break、goto、return などのステートメントは、プログラムのフローを別のセクションまたは関数に移します。このフローのエスケープにより、フロー制御コードに続くステートメントは統計的に実行されず、ステートメントは到達不能になります。
このチェックは、while(1) などのトリビアルな無限ループに続くコードも検出します。この種のループでは、プログラムの終了によってのみ、プログラムのフローが解放されます。このタイプの終了は、無限ループの後に来るコードが到達不能になる原因となります。
到達不能コードは開発時間、メモリ、および実行サイクルを浪費します。開発者は実行されないコードを保守しなければなりません。実行されない命令でも保存およびキャッシュされる必要があります。
修正方法は到達不能コードの意図する機能によって異なります。そのコードを実行する場合、コードの配置または制御フローを変えている先行ステートメントの配置をチェックします。たとえば、到達不能コードが return ステートメントの後にある場合、それらの順序を入れ替えるか、その return ステートメント全体を削除しなければならない可能性があります。
問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。
Polyspace ユーザー インターフェイスでのバグ修正または正当化による結果への対処 (Polyspace ユーザー インターフェイスで結果をレビューする場合)。
Polyspace Access でのバグ修正または正当化による結果への対処 (Polyspace Access) (Web ブラウザーで結果をレビューする場合)。
コードへの注釈付けと既知の結果または許容可能な結果の非表示 (IDE で結果をレビューする場合)
typedef enum _suit {UNKNOWN_SUIT, SPADES, HEARTS, DIAMONDS, CLUBS} suit;
suit nextcard(void);
void guess(suit s);
suit deal(void){
suit card = nextcard();
if( (card < SPADES) || (card > CLUBS) )
card = UNKNOWN_SUIT;
return card;
if (card < HEARTS) { //Noncompliant
guess(card);
}
return card;
}この例には、欠落している中かっこと、誤解を招くインデントがあります。1 番目の return ステートメントは、その関数が呼び出された箇所にコードのフローを戻します。この return ステートメントのために、if ブロックと 2 番目の return ステートメントは実行されません。
インデントと中かっこの修正を行うと、エラーが明確になります。
typedef enum _suit {UNKNOWN_SUIT, SPADES, HEARTS, DIAMONDS, CLUBS} suit;
suit nextcard(void);
void guess(suit s);
suit deal(void){
suit card = nextcard();
if( (card < SPADES) || (card > CLUBS) ){
card = UNKNOWN_SUIT;
}
return card;
if (card < HEARTS) { //Noncompliant
guess(card);
}
return card;
}1 つの修正方法として、escape ステートメントを削除します。この例では、最初の return ステートメントを削除して、最後の if ステートメントに到達します。
typedef enum _suit {UNKNOWN_SUIT, SPADES, HEARTS, DIAMONDS, CLUBS} suit;
suit nextcard(void);
void guess(suit s);
suit deal(void){
suit card = nextcard();
if( (card < SPADES) || (card > CLUBS) )
{
card = UNKNOWN_SUIT;
}
if(card < HEARTS)
{
guess(card);
}
return card;
}別の修正方法として、必要でなければ到達不能コードを削除します。関数は 2 番目の if ステートメントに到達しないため、これを削除するとコードが単純になり、しかもプログラムの動作は変更されません。
typedef enum _suit {UNKNOWN_SUIT, SPADES, HEARTS, DIAMONDS, CLUBS} suit;
suit nextcard(void);
void guess(suit s);
suit deal(void){
suit card = nextcard();
if( (card < SPADES) || (card > CLUBS) )
{
card = UNKNOWN_SUIT;
}
return card;
}int add_apples(int apple) {
int count = 1;
while(1) {
if(apple < 99){
apple++;
count++;
}else{
count--;
}
}
return count; //Noncompliant
}この例では、while(1) ステートメントにより無限ループが形成されています。この無限ループを終了させる方法はプログラムの終了のみであるため、この無限ループの後に来る return count は到達不能になります。
1 つの修正方法として、ループ条件を変更して while ループを有限にします。ここでの修正例では、if の条件 apple < 99 から構成したステートメントがループで使用されます。
int add_apples1(int apple) {
int count = 0;
while(apple < 99) {
apple++;
count++;
}
if(count == 0)
count = -1;
return count;
}別の修正方法として、無限ループからのブレークポイントを追加し、無限ループの後に来るコードへの到達を可能にします。この例では、break が else ブロックに追加され、return count ステートメントが到達可能になっています。
int add_apples(int apple) {
int count = 1;
while(1) {
if(apple < 99)
{
apple++;
count++;
}else{
count--;
break;
}
}
return count;
}別の修正方法として、到達不能コードを削除します。この修正によりコードがクリーンアップされ、確認と保守が容易になります。この例では、return ステートメントを削除し、関数の戻り値の型を void に変更しています。
void add_apples(int apple) {
int count = 1;
while(1) {
if(apple < 99)
{
apple++;
count++;
}else{
count--;
}
}
}チェック情報
| カテゴリ: Bad Coding Practices |
バージョン履歴
R2023a で導入
MATLAB Command
You clicked a link that corresponds to this MATLAB command:
Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.
Web サイトの選択
Web サイトを選択すると、翻訳されたコンテンツにアクセスし、地域のイベントやサービスを確認できます。現在の位置情報に基づき、次のサイトの選択を推奨します:
また、以下のリストから Web サイトを選択することもできます。
最適なサイトパフォーマンスの取得方法
中国のサイト (中国語または英語) を選択することで、最適なサイトパフォーマンスが得られます。その他の国の MathWorks のサイトは、お客様の地域からのアクセスが最適化されていません。
南北アメリカ
- América Latina (Español)
- Canada (English)
- United States (English)
ヨーロッパ
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)