メインコンテンツ

AUTOSAR C++14 Rule A20-8-2

A std::unique_ptr shall be used to represent exclusive ownership

説明

ルール定義

A std::unique_ptr shall be used to represent exclusive ownership.

根拠

ヒープ メモリへの生のポインターでは 2 つの関連する問題が発生します。

  • 生のポインターがスコープから外れると、ポインターが指していたメモリの割り当てが解除されず、メモリ リークを発生させる可能性があります。ポインターがスコープを外れる前にメモリを明示的に割り当て解除 (ポインターを delete) することを覚えておかなければなりません。

  • 関数に生のポインターを渡すと、ポインターが指すリソースに対してその関数が排他的所有権を持ちメモリを割り当て解除可能であるのか、それとも呼び出し元に割り当て解除をまかせなければならないのかが不明確です。関数がメモリを割り当て解除すると、同じメモリ ロケーションを指す別のポインターが使われないポインターとして残される危険があります。

std::unique_ptr オブジェクトは、両方の問題を解決し、生のポインターに対するオーバーヘッドが大きく増えないスマート ポインターです。

  • ポインターが指すメモリを明示的に割り当て解除する必要はありません。メモリは、ポインターがスコープを外れる前に割り当て解除されます。

  • ポインターは指しているオブジェクトの排他的所有権を持ちます。ポインターを移動演算で関数に渡すと、その関数はポインターを通じてメモリの所有権があるものと見なし、完了時にメモリを暗黙的に割り当て解除します (他の関数に所有権を渡していない場合)。

Polyspace 実装

チェッカーは、パラメーターまたは戻り値として生のポインターを使用する main 以外の関数にフラグを設定します。

チェッカーはこのルールと AUTOSAR C++14 Rule A20-8-3 の両方の違反を報告します。

  • ポインターが指すオブジェクトに対して関数が排他的所有権を持つ場合は、生のポインターを std::unique_ptr 型に変換してください。

  • ポインターが指すオブジェクトに対して関数が共有所有権を持つ場合は、生のポインターを std::shared_ptr 型に変換してください。

トラブルシューティング

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

すべて展開する

#include <memory>
#include <cstdint>
#include <thread>
constexpr std::uint32_t SIZE=100;

class Resource {
  public:
    bool lookup(std::int32_t);
  private:
    std::int32_t arr[SIZE];
};

bool doesValueExist(Resource *aResource, std::int32_t val) { //Noncompliant
    return aResource->lookup(val);
}

bool doAllSmallerValuesExist(std::unique_ptr<Resource> aResource, std::int32_t val) { 
//Compliant
    bool valueExists = true;
    for(std::int32_t i = 0; i <= val; i++) {
        valueExists = aResource->lookup(i);
        if(!valueExists)
            break;
    }
    return valueExists;
}

std::int32_t getAVal();

void main(void) {
    Resource *aResourcePtr = new Resource;
    auto anotherResourcePtr = std::make_unique<Resource>();
    bool valueFound, allSmallerValuesFound;
    
    //Initialize resources
    
    valueFound = doesValueExist(aResourcePtr, getAVal());
    allSmallerValuesFound = doAllSmallerValuesExist(std::move(anotherResourcePtr), getAVal());
}

この例では、関数 doesValueExist はパラメーターとして Resource オブジェクトを指す生のポインターを取っており、このルールに違反しています。

関数 doAllSmallerValuesExistResource オブジェクトに同様の操作を実行しますが、パラメーターとしてオブジェクトへの std::unique_ptr ポインターを取ります。

チェック情報

グループ: General utilities library
カテゴリ: Required、Automated

バージョン履歴

R2020b で導入