22

我正在 MinGW GCC 4.4.0 中编译一些 c++ 代码,并收到以下形式的警告...

warning: invalid access to non-static data member '<membername>'  of NULL object
warning: (perhaps the 'offsetof' macro was used incorrectly)

这个问题似乎很熟悉——我之前尝试过解决但失败了,我想,但不久前。该代码在 Visual C++ 中构建良好,但我最近没有在任何其他编译器中构建此特定代码。

问题代码是以下模板...

template<typename T>
class c_Align_Of
{
  private:
    struct c_Test
    {
      char m_Char;
      T    m_Test;
    };
  public:
    enum { e_Align = offsetof (c_Test, m_Test) };
};

显然,我可能可以使用一些条件编译来为此使用特定于编译器的函数,并且我相信 C++0x 将(最终)使其变得多余。但无论如何,我看不出这种使用offsetof.

非常迂腐,有可能因为T参数类型有时是非 POD,所以 GCC 类c_Test为非 POD 并抱怨(并且抱怨和抱怨 - 我收到近 800 行这些警告)。

这对于标准的严格措辞来说是很顽皮的,因为非 POD 类型可能会破坏offsetof. 但是,这种非 POD 在实践中应该不是问题 -c_Test不会有虚拟表,也不需要运行时诡计来找到m_Test.

此外,即使c_Test有一个虚拟表,GCC 也使用一个内在函数来实现 offsetof 宏,该内在函数总是在编译时根据该特定类型的静态布局进行评估。提供一个工具,然后每次使用它时都会抱怨(抱歉,警告)似乎很愚蠢。

而且,我不是这里唯一一个做这种事情的人......

对合法使用偏移量问题的回答

确实记得offsetof因为这种原因遇到过问题,但我认为问题不在于这个模板。

有任何想法吗?

4

1 回答 1

36

哎呀...

问题在于结构c_Test是非 POD,因为 T 类型是非 POD。这是来自 GCC 手册的引用...

-Wno-invalid-offsetof(仅限 C++ 和 Objective-C++)

禁止将“offsetof”宏应用于非 POD 类型的警告。

根据 1998 ISO C++ 标准,将“offsetof”应用于非 POD 类型是未定义的。然而,在现有的 C++ 实现中,“offsetof”通常会给出有意义的结果,即使应用于某些类型的非 POD 类型也是如此。(例如一个简单的 'struct' 仅由于具有构造函数而不能成为 POD 类型。)此标志适用于意识到他们正在编写不可移植代码并且故意选择忽略有关它的警告的用户。

在 C++ 标准的未来版本中,对 'offsetof' 的限制可能会放宽。

我的问题是我几乎所有的 T 类型都有构造函数,因此被归类为非 POD。我之前忽略了这一点,因为它无关紧要——当然,原则上它应该与 offsetof 无关。问题是 C++ 标准使用一个 POD 与非 POD 分类,即使有许多不同的方式可以成为非 POD,并且编译器默认警告不符合标准的使用是正确的。

我目前的解决方案将是上面的选项来抑制警告 - 现在我只需要弄清楚如何告诉 cmake 使用它。

于 2010-06-28T06:06:15.660 回答