如何避免C ++匿名对象(How to avoid C++ anonymous objects)

2019-09-01 01:32发布

我有一个ScopedLock类运行的范围时,它可以帮助自动释放锁。 然而,问题是:有时候,团队成员编写无效的锁码,如

{
    ScopedLock(mutex);   // anonymous
    xxx;
}

上面的代码是错误的,因为ScopedLock对象被构造并立即破坏,所以锁定失败预期的区域( xxx )。 我希望编译器试图编译这样的代码时,给出一个错误。 可以这样做?

我已搜查g++的警告选项,但未能找到合适的人。

Answer 1:

为了避免这种情况,引入宏观其可以实现这个要求,始终使用相同的名称更衣室:

#define LOCK(mutex) ScopedLock _lock(mutex)

然后使用它是这样的:

{
    LOCK(mutex);
    xxx;
}

作为替代方案,Java的synchronize块可以使用宏结构进行模拟:在for循环总是运行只出现一次,我在for循环,所以它离开时被摧毁的初始化语句实例化这样一个更衣室的for循环。

然而,它有一些缺陷,一个意想不到的行为break声明就是一个例子。 这种“黑客”被引入这里 。


当然,没有上述方法完全避免意外的代码喜欢你的例子。 但是,如果你用来编写使用两个宏的一个锁定的互斥锁,将不太可能发生。 至于更衣室类的名字将永远不会再在代码中显示,除了在宏定义,你甚至可以在版本控制系统引入commit钩子,以避免犯无效的代码。



Answer 2:

我已经看到了一个代码库中一个有趣的把戏,但如果你的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);

这不会触发宏。



Answer 3:

不,遗憾的是没有办法做到这一点 , 因为我在博客中探讨了去年 。

在这里面,我的结论是:

我想这个故事的寓意是使用时要记住这个故事scoped_lock秒。


你可以尝试迫使所有的程序员在你的团队使用宏,或一定范围的换招,但当时如果你能保证在任何情况下,你最好能保证在任何情况下抓住这个bug也。

您正在寻找一种方法以编程方式赶上当它是由这个特定的错误,是没有的。



Answer 4:

您可以使用类和删除功能具有相同的名称。 不幸的是,这需要的类型前添加“类”的关键字。

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;
}


Answer 5:

AFAIK有没有这样的海湾合作委员会的标志。 静态分析可能更适合您的需求。



Answer 6:

与宏替换

#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



文章来源: How to avoid C++ anonymous objects
标签: c++ g++