2011-06-29 72 views
11

考虑下面的代码:为什么没有gcc/g ++警告不使用临时对象?

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的描述观察者模式的实现) 用户干预这里是为了保护连接()和所述通知()从同时运行,因此boost :: unique_lock。 目标是保护subscribers容器。

但确实很难发现这些锁实际上只是临时的(仔细一看,没有为他们指定名称)。 因此,当临时文件被破坏时,互斥锁就会立即释放,即代码不是线程安全的。 我希望在这种情况下编译器警告。像“未使用的临时”。

更糟的是,cppcheck也不会识别这个错误。 (cppcheck:c/C++代码分析工具http://sourceforge.net/apps/mediawiki/cppcheck/index.php?title=Main_Page

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

+1

我做了一个类似的错误,检查这个问题太:http://stackoverflow.com/questions/914861/disallowing-creation-of-the-temporary-objects – Naveen

+0

你尝试了-Wall -Wextra作为命令行参数编译器?虽然我不熟悉C++ .. – DipSwitch

+0

确保一个unamed变量(被称为* temporary *)被立即销毁?我希望它能活到它定义的范围结束。 – ereOn

回答

8

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

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

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

A(); 

在情况下,如果这样的更新是没有发生,编译器将不会挖成的A构造,并检查是否有用的事情正在发生。它总是假定为有效的场景。有很多这样的情况可以指出与临时工有关。

+7

事实上,在这个问题提出的情况下,发生了某些事情*:互斥锁被锁定并释放,触发跨线程的缓存同步......编译器如何知道这不是所有想要的? –

+1

编程器每次程序员做出可能有危险的事情时都应该发出警告。例如,当你做一些类似“if(i = 0)”的事时,你可能想写“if(i == 0)”。你有可能故意这样做(例如“if(result = doSomething())”,但由于它通常不是你想要的,所以会有一个警告,不应该是临时变量的情况吗? – petersohn

0

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

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

而在模板元编程中,可能会创建并销毁一个临时的,以防万一用户提供带有副作用的类。当一个没有副作用的简单类用于实例化模板时,警告将出现在模板代码的内部。

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

所以我期望编译器厂商已经决定在其他地方花费更多的时间。

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”,则会发生什么情况。