Ale*_*op. 2 c++ multithreading compiler-warnings c++11
我实现了一个应该是线程安全的共享库.保护我std::lock_guard<std::mutex>在C++ 11标准中使用的关键区域.
错字是我省略了对象本身:
std::lock_guard<std::mutex>(getMutexObj());
Run Code Online (Sandbox Code Playgroud)
代替
std::lock_guard<std::mutex> lock_obj(getMutexObj());
Run Code Online (Sandbox Code Playgroud)
并在每个地方复制/粘贴它...不用说,当多线程应用程序开始无法预测崩溃时,我花了一段时间才导致它.
只是为了涵盖所有要点,声明getMutexObj()和互斥体本身如下:
...
mutable std::mutex m_mutex;
...
std::mutex& getMutexObj() const
{
return m_mutex;
}
Run Code Online (Sandbox Code Playgroud)
g++ 5.2.0使用以下警告标志编译所有代码:
WARNINGS := -pedantic \
-Wall \
-Wextra \
-Werror \
-Wconversion \
-Woverloaded-virtual \
-Wcast-qual \
-Wctor-dtor-privacy \
-Wdisabled-optimization \
-Wuninitialized \
-Wformat=2 \
-Winit-self \
-Wlogical-op \
-Wmissing-declarations \
-Wmissing-include-dirs \
-Wold-style-cast \
-Wredundant-decls \
-Wshadow \
-Wsign-conversion \
-Wsign-promo \
-Wstrict-null-sentinel \
-Wstrict-overflow=5 \
-Wswitch-default \
-Wundef \
-Wunused \
-Wfloat-equal \
-Wsuggest-final-methods \
-Wsuggest-final-types \
-Wzero-as-null-pointer-constant
Run Code Online (Sandbox Code Playgroud)
为什么编译器没有触发任何警告std::lock_guard<std::mutex>(getMutexObj());?
我尝试了以下代码,看看编译器是否会抛出警告:
std::lock_guard<std::mutex>(getMutexObj());
int(23);
23;
uint16_t remove_me = 23;
Run Code Online (Sandbox Code Playgroud)
对于2,3和4号线,我收到警告但不是第1行......为什么?
<.../path/...>:32:16: error: statement has no effect [-Werror=unused-value]
int(23);
^
<.../path/...>:33:11: error: statement has no effect [-Werror=unused-value]
23;
^
<.../path/...>:34:18: error: unused variable 'remove_me' [-Werror=unused-variable]
uint16_t remove_me = 23;
^
cc1plus: all warnings being treated as errors
Run Code Online (Sandbox Code Playgroud)
EDIT1
我注意到这个问题有点令人困惑,因为几乎所有答案都与之相关
对于2,3和4号线,我收到警告但不是第1行......为什么?
然而,真正的问题是:
为什么编译器没有触发任何警告std::lock_guard<std::mutex>(getMutexObj());?
是否有任何开关使编译器警告这样的代码?
EDIT2
正如他在评论中提到的cpplearner,std::lock_guard<std::mutex>(getMutexObj());被视为函数声明的函数声明getMutexObj返回std::lock_guard<std::mutex>.
我查看了反汇编,看到了如果std::lock_guard<std::mutex>(getMutexObj());没有相关的操作码.
但是当我改成它时
std::lock_guard<std::mutex>{getMutexObj()};
Run Code Online (Sandbox Code Playgroud)
并查看了反汇编,它被编译为临时对象创建,但再次没有任何警告.
与23;消息"错误:语句无效"不同,创建未命名的临时lock_guard 确实具有锁定和解锁互斥锁的效果.
这具有其他线程可见的内存屏障的副作用.
std::lock_guard<std::mutex>(getMutexObj());
Run Code Online (Sandbox Code Playgroud)
这实际上应该给出一个错误,因为它声明了一个被调用的函数getMutexObj但是已经使用不同的返回类型声明了(并且你不能在返回类型上重载).这是一个GCC错误,我已将其报告为错误69855.
这种情况不同:
std::lock_guard<std::mutex>{getMutexObj()};
Run Code Online (Sandbox Code Playgroud)
这确实创建了一个临时的,但这里没有警告,因为编译器不是魔术.
警告被添加到编译器以捕获常见错误,但有人必须实际执行代码来检查它,并发出警告.这不仅仅发生在魔法或仙女的到来,并且在没有人看的时候在晚上改进了编译器.
在这种情况下,编译器会看到您正在创建一个临时变量,它具有副作用(它写入全局内存位置,互斥锁并发出内存障碍).编译器不知道那些副作用并不完全是你想要做的,因为它不是魔术.
如果编译器在这里发出警告会很好,有人确实为GCC写了一个补丁来警告这个,请参阅错误36587,但正如我在该错误报告中指出的那样,它也会警告有效的代码.如果编译器在每次创建具有副作用的临时变量时发出警告,那将是很糟糕的.这是使用类似语法的有效方案:
std::ofstream( "./lockfile" );
Run Code Online (Sandbox Code Playgroud)
这将打开一个ofstream具有特定名称的文件,如果该文件尚不存在,则会创建该文件.编译器不应该警告这一点,因为它完全有效.
因此,为了警告您的示例,而不是其他类似的代码片段,需要一些额外的信息来告诉编译器该lock_guard类型永远不应该以这种方式使用.这意味着以lock_guard某种方式注释并教导编译器识别该注释.同样,仙女不会来做这项工作,所以它没有发生,因为它没有被优先考虑,没有人写过补丁.
GCC支持warn_unused构造函数的属性,参见bug 55203,但这无济于事,lock_guard因为正确使用类意味着它总是"未使用"(在构造之后你永远不会引用它).对于这种情况,需要实现不同的属性和警告.
| 归档时间: |
|
| 查看次数: |
292 次 |
| 最近记录: |