What is wrong with this use of offsetof?

Steve314 picture Steve314 · Jun 28, 2010 · Viewed 15.1k times · Source

I'm compiling some c++ code in MinGW GCC 4.4.0, and getting warnings with the following form...

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

This problem seems familiar - something I've tried to resolve before and failed, I think, but a while ago. The code builds fine in Visual C++, but I haven't built this particular code recently in any other compiler.

The problem code is the following template...

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

Obviously I can probably use some conditional compilation to use compiler-specific functions for this, and I believe C++0x will (at long last) make it redundant. But in any case, I cannot see anything wrong with this use of offsetof.

Very pedantically, it's possible that because the T parameter types are sometimes non-POD, so GCC classes c_Test as non-POD and complains (and complains and complains - I'm getting nearly 800 lines of these warnings).

This is naughty by the strict wording of the standard, since non-POD types can break offsetof. However, this kind of non-POD shouldn't be a problem in practice - c_Test will not have a virtual table, and no run-time trickery is needed to find the offset of m_Test.

Besides, even if c_Test had a virtual table, GCC implements the offsetof macro using an intrinsic that is always evaluated at compile-time based on the static layout of that particular type. Providing a tool then whining (sorry, warning) every time it's used just seems silly.

Also, I'm not the only person around here who does this kind of thing...

Answer to legit-uses-of-offsetof question

I do remember having an issue with offsetof for this kind of reason, but I don't think the problem was this template.

Any ideas?

Answer

Steve314 picture Steve314 · Jun 28, 2010

Oops...

The issue is with the c_Test struct being non-POD due to the T type being non-POD. Here's a quote from the GCC manual...

-Wno-invalid-offsetof (C++ and Objective-C++ only)

Suppress warnings from applying the ‘offsetof’ macro to a non-POD type.

According to the 1998 ISO C++ standard, applying ‘offsetof’ to a non-POD type is undefined. In existing C++ implementations, however, ‘offsetof’ typically gives meaningful results even when applied to certain kinds of non-POD types. (Such as a simple ‘struct’ that fails to be a POD type only by virtue of having a constructor.) This flag is for users who are aware that they are writing nonportable code and who have deliberately chosen to ignore the warning about it.

The restrictions on ‘offsetof’ may be relaxed in a future version of the C++ standard.

My problem is that almost all my T types have constructors, and are therefore classed as non-POD. I ignored this point as irrelevant earlier - and of course it should be irrelevant for offsetof in principle. The trouble is that the C++ standard uses the one POD vs. non-POD classification even though there are a number of distinct ways to be non-POD, and the compiler is correct to warn about non-standards-compliant use by default.

My solution for the moment will be the option above to suppress the warning - now I just need to figure out how to tell cmake to use it.