【问题标题】:Why is there no gcc/g++ warning for unused temporaries?为什么没有针对未使用的临时对象的 gcc/g++ 警告?
【发布时间】:2011-09-24 23:45:27
【问题描述】:

考虑以下代码:

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:一个c/c++代码分析工具http://sourceforge.net/apps/mediawiki/cppcheck/index.php?title=Main_Page)

Gcc 对未使用的变量发出警告。这里的临时变量是一个未使用的变量,肯定是程序员疏忽的结果。 那么,为什么在这种情况下没有警告呢?也许发现这种情况太复杂了?

【问题讨论】:

  • 我犯了类似的错误,也检查这个问题:stackoverflow.com/questions/914861/…
  • 您是否尝试将 -Wall -Wextra 作为编译器的命令行参数?不过我对 C++ 并不熟悉..
  • 是否保证一个未命名的变量(称为临时)被立即销毁?我原以为它会一直存在到它定义的范围结束。
  • @ereOn:它一直存在到语句结束:/
  • @Matthieu M.:好的,谢谢。很高兴知道。 :)

标签: c++ thread-safety gcc-warning temporaries


【解决方案1】:

编译器不会发出警告,因为您很可能正在更新构造函数中的某些static-member / global 变量(这是有效且有意义的)。例如:

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

现在当你简单地调用一个临时的:

A();

如果没有发生这样的更新,编译器将不会深入A 的构造函数并检查是否发生了有用的事情。它总是假设是一个有效的场景。可以指出与临时工有关的这种情况很多。

【讨论】:

  • 确实,在问题提出的情况下 is 发生了一些事情:互斥锁被锁定和释放,触发了跨线程的缓存同步......编译器怎么知道这还不是我们想要的吗?
  • 每次程序员做一些潜在危险的事情时,编译器都应该发出警告。例如,当您执行“if (i = 0)”之类的操作时,您可能想写“if (i == 0)”。您可能是故意这样做的(例如“if (result = doSomething())”,但由于它通常不是您想要的,因此有一个警告。临时变量不应该也是这种情况吗?
【解决方案2】:

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

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

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

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

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

【讨论】:

    【解决方案3】:

    hmm.. 我不确定,但这不能用普通的 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”会发生什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-13
      • 2018-09-04
      • 1970-01-01
      • 1970-01-01
      • 2017-01-19
      • 1970-01-01
      • 2013-04-08
      • 2018-12-31
      相关资源
      最近更新 更多