11

次のコードを検討してください。

void ListenerImpl::attach(boost::shared_ptr<ISubscriber> subscriber)
{
    boost::unique_lock<boost::mutex>(mtx);
    subscribers.push_back(subscriber);
}

void ListenerImpl::notify(MsgPtr msg)
{
    boost::unique_lock<boost::mutex>(mtx);

    //notify all subscribers
    BOOST_FOREACH(boost::shared_ptr<ISubscriber> subscriber, subscribers){
        subscriber->update(msg);
    }

}

(これは、GoFで説明されているオブザーバーパターンの実装です。)ここでのユーザー介入は、attach()とnotify()を同時に実行しないように保護することでした。したがって、boost::unique_lockです。目標は、subscribersコンテナを保護することでした。

しかし、ロックが実際には一時的なものであることに気付くのは非常に困難です(詳しく見てみると、名前は割り当てられていません)。したがって、一時的なものが破棄されると、ミューテックスのロックはすぐに解放されます。つまり、コードはスレッドセーフではありません。このような状況では、コンパイラの警告が予想されます。「未使用の一時的」のようなもの。

さらに悪いことに、cppcheckはこの間違いも認識しません。(cppcheck:ac / c ++コード分析ツールhttp://sourceforge.net/apps/mediawiki/cppcheck/index.php?title=Main_Page

Gccは、未使用の変数に対して警告を発行します。ここでの一時的な変数は未使用の変数であり、間違いなくプログラマーの不注意の結果です。では、なぜこのような場合に警告がないのでしょうか。たぶん、そのような状況を発見するのは複雑すぎますか?

4

3 に答える 3

8

static-member / globalコンストラクター内の変数(有効で意味のあるもの)を更新している可能性が高いため、コンパイラーは警告を発行しません。例えば:

struct A
{
  static int count;
  A () { count ++; }
};

今、あなたが単に一時的なものを呼び出すとき:

A();

そのような更新が行われていない場合、コンパイラーはのコンストラクターを掘り下げて、A何か有用なことが起こっているかどうかをチェックしません。それは常に有効なシナリオであると想定しています。一時的なものに関連して指摘できるケースはたくさんあります。

于 2011-06-29T09:28:01.283 に答える
0

it++;提案された警告は、多くのforループに見られるすべてのに対しても発行されることに注意してください。

iammilindは、副作用がある場合に、臨時雇用者を作成してすぐに破壊することが意図されている場合があることをすでに述べています。

また、テンプレートメタプログラミングでは、ユーザーがクラスに副作用を提供した場合に備えて、一時的なものを作成および破棄する場合があります。副作用のない単純なクラスを使用してテンプレートをインスタンス化すると、テンプレートコードの奥深くに警告が表示されます。

そのため、提案された警告には多くの誤検知があります。偽の警告の中から本物の警告を見つけるのは難しいでしょう。

ですから、コンパイラベンダーは自分たちの時間を他の場所で過ごすほうがよいと判断したと思います。

于 2011-06-29T10:25:31.997 に答える
0

うーん..わかりませんが、通常のC ++でもこれを保護することはできませんか?

class Mutex;
class Lock {
    Lock(Mutex *mutex);
};

int main() {
    Lock /* lock */ (&mtx);
    return 0;
}

DJGPPでコンパイルすると、次のコンパイラ警告が表示されます。

C:\df>gxx -c a.cpp
a.cpp: In function 'int main()':
a.cpp:8:30: error: 'mtx' declared as reference but not initialized

「ロック」のコメントを外してミューテックス変数を追加すると、正常にコンパイルされます。

したがって、「mtx」変数がポインタの場合。変更して「&mtx」として渡すとどうなりますか。

于 2011-06-30T13:01:43.173 に答える