我有一个ScopedLock
类运行的范围时,它可以帮助自动释放锁。 然而,问题是:有时候,团队成员编写无效的锁码,如
{
ScopedLock(mutex); // anonymous
xxx;
}
上面的代码是错误的,因为ScopedLock
对象被构造并立即破坏,所以锁定失败预期的区域( xxx
)。 我希望编译器试图编译这样的代码时,给出一个错误。 可以这样做?
我已搜查g++
的警告选项,但未能找到合适的人。
我有一个ScopedLock
类运行的范围时,它可以帮助自动释放锁。 然而,问题是:有时候,团队成员编写无效的锁码,如
{
ScopedLock(mutex); // anonymous
xxx;
}
上面的代码是错误的,因为ScopedLock
对象被构造并立即破坏,所以锁定失败预期的区域( xxx
)。 我希望编译器试图编译这样的代码时,给出一个错误。 可以这样做?
我已搜查g++
的警告选项,但未能找到合适的人。
为了避免这种情况,引入宏观其可以实现这个要求,始终使用相同的名称更衣室:
#define LOCK(mutex) ScopedLock _lock(mutex)
然后使用它是这样的:
{
LOCK(mutex);
xxx;
}
作为替代方案,Java的synchronize
块可以使用宏结构进行模拟:在for循环总是运行只出现一次,我在for循环,所以它离开时被摧毁的初始化语句实例化这样一个更衣室的for循环。
然而,它有一些缺陷,一个意想不到的行为break
声明就是一个例子。 这种“黑客”被引入这里 。
当然,没有上述方法完全避免意外的代码喜欢你的例子。 但是,如果你用来编写使用两个宏的一个锁定的互斥锁,将不太可能发生。 至于更衣室类的名字将永远不会再在代码中显示,除了在宏定义,你甚至可以在版本控制系统引入commit钩子,以避免犯无效的代码。
我已经看到了一个代码库中一个有趣的把戏,但如果你的scoped_lock类型不是一个模板(的std :: scoped_lock的是)它才会起作用。
#define scoped_lock(x) static_assert(false, "you forgot the variable name")
如果你正确地使用类,你有
scoped_lock lock(mutex);
并且由于scoped_lock的标识符没有后跟一个开放括号,宏不会触发和代码将保持原样。 如果你写\
scoped_lock(mutex);
宏将触发和代码将与被取代
static_assert(false, "you forgot the variable name");
这将产生一个提示消息。
如果你使用一个合格的名字
threads::scoped_lock(mutext);
那么结果将仍然无法编译,但消息不会那样好。
当然,如果你的锁是一个模板,坏的代码
scoped_lock<mutex_type>(mutex);
这不会触发宏。
不,遗憾的是没有办法做到这一点 , 因为我在博客中探讨了去年 。
在这里面,我的结论是:
我想这个故事的寓意是使用时要记住这个故事
scoped_lock
秒。
你可以尝试迫使所有的程序员在你的团队使用宏,或一定范围的换招,但当时如果你能保证在任何情况下,你最好能保证在任何情况下抓住这个bug也。
您正在寻找一种方法以编程方式赶上当它是由这个特定的错误,是没有的。
您可以使用类和删除功能具有相同的名称。 不幸的是,这需要的类型前添加“类”的关键字。
class Guard
{
public:
explicit Guard(void)
{
}
};
static void Guard(void) = delete;
int main()
{
// Guard(); // Won't compile
// Guard g; // Won't compile
class Guard g;
}
AFAIK有没有这样的海湾合作委员会的标志。 静态分析可能更适合您的需求。
与宏替换
#define CON2(x,y) x##y
#define CON(x,y) CON2(x,y)
#define LOCK(x) ScopedLock CON(unique_,__COUNTER__)(mutex)
用法
{
LOCK(mutex);
//do stuff
}
这个宏会产生锁的唯一名称,允许范围内的其他互斥的lockeng