メインコンテンツ

AUTOSAR C++14 Rule A27-0-4

C-style strings shall not be used

R2021a 以降

説明

ルール定義

C-style strings shall not be used.

根拠

C スタイルの文字列を保存する基となる文字配列には、次のようなさまざまな欠点があります。

  • 非トリビアルなメモリ操作が必要な文字列に対する操作を実行する場合は、メモリの割り当てと割り当て解除を明示的に処理する必要があります。

  • char* が単一の文字を指しているのか、C スタイルの文字列を指しているのかは必ずしも明確ではありません。

  • 配列を値またはポインターとして関数に渡すときに、誤って生のポインターに変換してしまった場合は、配列サイズに関する情報が消失します (配列減衰)。たとえば、次のコード スニペットでは、funccString の最初の文字へのポインターのサイズ (8) を出力しますが、cString の実際のサイズは 6 です。

    void func(char *c){ //function takes array by value
      cout << sizeof(c);
    }
    
    void main(){
      char cString[]{ "pizza" }; //Size is 6 (5 characters + null terminator)
      func(cString); // Size is 8 (size of char*)
    }

代わりに、std::string クラスを使用して文字のシーケンスを保存します。このクラスは、割り当てと割り当て解除を処理し、安全に関数に渡すことが可能なオブジェクトをインスタンス化します。また、このクラスには、反復子などの文字列を操作するための機能が組み込まれています。

Polyspace 実装

Polyspace® は以下の使用にフラグを設定します。

  • 文字へのポインター (char*) と文字の配列 (char someArray[])。

  • volatileconst などの型修飾子を使用した文字へのポインターと文字の配列。たとえば、char const* です。

  • wchar_t 型、char16_t 型、および char32_t 型へのポインターと配列。

ソース コード内に関数宣言と関数定義が含まれている場合は、Polyspace がその関数定義を違反とします。以下に例を示します。

const char* greeter(void);
//....
const char* greeter(void){ //Non-compliant
  return "Hello"; 
}

Polyspace は、次の使用にフラグを設定しません。

  • signed 文字または unsigned 文字へのポインターまたは配列。たとえば、次のコード スニペット内の signed_cunsigned_arr にはフラグが設定されません。

    signed char* signed_c;
    unsigned char unsigned_arr[2048];

  • リテラル文字列。たとえば、次のコード スニペット内の greeter() の戻り値にはフラグが設定されませんが、最初の行内の const char* の使用にはフラグが設定されます。

    const char* greeter(void){ //Non-compliant
      return "Hello"; // Compliant
    }

  • main() のパラメーター。

トラブルシューティング

ルール違反が想定されるものの、Polyspace から報告されない場合は、コーディング規約違反が想定どおりに表示されない理由の診断を参照してください。

すべて展開する

#include<iostream>
#include <string>
#include<cstring>

char* sub_c_str(   //Non-compliant
    const char* str1, const int delim)  //Non-compliant
{
    size_t index {strlen(str1)};
    if (strchr(str1, delim)) {
        index = (size_t)(strchr(str1, delim) - str1);
    }
    char* p = (char*) malloc(index + 1); //Non-compliant
    //memory leak if p is not freed by caller
    strncpy(p, str1, index);
    return p;

}

std::string sub_str(std::string const str2, const char delim)
{
    return str2.substr(0, str2.find(delim));
}

int main()
{
    const char str1[] { "rootFolder/subFolder"}; // Non-compliant
    std::cout << sub_c_str(str1, '/') << std::endl;

    std::string const str2 { "rootFolder/subFolder" };
    std::cout << sub_str(str2, '/') << std::endl;
    return 0;
}

この例では、関数 sub_c_str が C スタイルの文字列パラメーター str1delim の最初のインスタンスの前までの部分文字列を返します。sub_c_str の戻り値の型と最初のパラメーターはどちらも文字への非準拠ポインターです。部分文字列を格納するポインター p も非準拠です。p に割り当てられたメモリをプログラムの終了前に開放していない場合は、それがメモリ リークにつながることに注意してください。

関数 sub_str は、std::string クラスを利用して、sub_c_str と同じ操作を実行します。このクラスは、メモリの割り当てと割り当て解除を処理します。また、このクラスには、文字列操作を実行するための機能 (findsubst) が組み込まれています。

チェック情報

グループ: Input/output library
カテゴリ: Required、Automated

バージョン履歴

R2021a で導入