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

嗯..我不确定,但这不能用普通的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 回答
0

请注意,您提出的警告也将针对 every 发出it++;,这在许多 for 循环中都可以找到。

iammilind 已经提到,有时它是有意创建并立即销毁 temp:当有副作用时。

在模板元编程中,可能会创建和销毁一个临时对象,以防万一用户提供具有副作用的类。当使用一个没有副作用的简单类来实例化模板时,模板代码的深处会出现警告。

因此,您提出的警告会有很多误报。在虚假警告中很难找到真正的警告。

所以我希望编译器供应商已经决定他们的时间最好花在其他地方。

于 2011-06-29T10:25:31.997 回答