在我们公司,直到最近,我们还没有使用命名空间,因为一些编译器不能很好地支持它们。

这导致以下错误的多次发生:

文件_A.cpp

class Node {
    Data *ptr;
    Node() { ptr = new Data; }
    ~Node() { delete ptr; }
};

file_B.cpp
class Node {
    vector<int> v;
    Point *pt;
    Node(int x,int y) { pt = new Point(x,y); v.push_back(0); }
    ~Node() { delete pt; }
};

void foo() {
    Node n(10,10);
    ...
}    // calls file_B::~Node() !!!

每个作者 Node 都不知道另一个 Node 的存在,但由于他预计这个类名可能会被重用,所以他没有用它创建一个 .hpp 文件。

编译器默默地删除其中一个析构函数,因为它们的签名匹配,并且很难找到该错误,因为它可能不会在不同的计算机中复制。

一旦发现错误,人们逐渐意识到它,并尝试将定义密封在未命名的命名空间中,或者避免内联类主体中的成员函数[见下文]。
  • 问题1: 既然你不相信程序员会一直记得防御性编程,那么有没有一种工具可以检测这些“非故意的弱链接符号”?

    无意中我的意思是,Node 类没有在 .hpp 文件中定义,并且至少有一个类成员在类定义之间不匹配......
  • 问题2: 如果我们不使用命名空间,而是内联每个函数,是否有可能自动生成的函数(copy-ctor、copy-assignment、destructor)会产生上述“弱链接错误” “?


  • 方式 1:包含在未命名的命名空间中
    namespace {
      class Node {
         Data *ptr;
         Node() { ptr = new Data; }
         ~Node() { delete ptr; }
      };
    }
    

    方式二:避免内联
    class Node {
       Data *ptr;
       Node();
       ~Node();
    };
    
    Node::Node()  { ptr = new Data; }
    Node::~Node() { delete ptr; }
    

    最佳答案

    如果您的代码库足够大,可以证明努力是合理的,您可以 自定义现有编译器 来解决您的问题:

  • LLVM/Clang 编译器是可定制的(它是用 C++ 编写的,我不太了解)。
  • GCC 编译器(最近的版本,如 4.6 )是可扩展的,可以通过用 C 编码的插件,或通过用 MELT 编码的扩展。 MELT 是一种(免费的,GPLv3 许可的)高级域特定语言,用于扩展 GCC。

  • 在这两种情况下,都需要几天或几周的时间,最困难的是部分理解编译器内部表示(GCC 的 Gimple & Tree)和组织(例如 pass)。

    我是 MELT 的主要作者,我很乐意帮助您解决 MELT,所以请随时与我联系。

    关于c++ - 检测意外的弱链接符号,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8318146/

    10-13 07:53