メインコンテンツ

AUTOSAR C++14 Rule A20-8-3

A std::shared_ptr shall be used to represent shared ownership

説明

ルール定義

A std::shared_ptr shall be used to represent shared ownership.

根拠

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

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

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

std::shared_ptr オブジェクトは両方の問題を解決するスマート ポインターです。

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

  • ポインターは指しているオブジェクトに対する共有所有権を持ちます。ポインターを関数に渡すと、その関数はポインターを通じてメモリの所有権があるものと見なし、他のどのポインターもそのオブジェクトを指していなければ、完了時にメモリを暗黙的に割り当て解除します。

std::shared_ptr オブジェクトは生のポインターと比較していくらかのオーバーヘッドがありますが、このオブジェクトを使用することにより、後でメモリ リークを発生させる可能性を回避できます。

Polyspace 実装

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

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

  • ポインターが指すオブジェクトに対して関数が排他的所有権を持つ場合は、生のポインターを 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::shared_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_shared<Resource>();
    bool valueFound, allSmallerValuesFound;
    
    //Initialize resources
    
    valueFound = doesValueExist(aResourcePtr, getAVal());
    allSmallerValuesFound = doAllSmallerValuesExist(anotherResourcePtr, getAVal());
}

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

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

チェック情報

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

バージョン履歴

R2020b で導入