Что не так с этим использованием offsetof? - PullRequest
20 голосов
/ 28 июня 2010

Я компилирую некоторый код на С ++ в MinGW GCC 4.4.0 и получаю предупреждения в следующей форме ...

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 реализует смещение макроса, используя встроенную функцию, которая всегда оценивается во время компиляции на основе статической компоновки этого конкретного типа.Предоставление инструмента и нытье (извините, предупреждение) каждый раз, когда он используется, кажется глупым.

Кроме того, я здесь не единственный, кто делает подобные вещи ...

Ответ на вопрос о законном использовании смещения

I do Помните, что у меня была проблема с offsetof по этой причине, но я не думаю проблема была в этом шаблоне.

Есть идеи?

1 Ответ

34 голосов
/ 28 июня 2010

Упс ...

Проблема в с структурой c_Test, не являющейся POD, поскольку тип T не является POD. Вот цитата из руководства GCC ...

-Wno-invalid-offsetof (только C ++ и Objective-C ++)

Подавить предупреждения от применения Макрос «offsetof» для типа, отличного от POD.

Согласно ISO C ++ 1998 года. стандарт, применяя «смещение» к не POD тип не определен. В существующих Реализации C ++, однако, «Offsetof» обычно дает значимый результаты даже применительно к определенным виды не POD типов. (Такой как простая «структура», которая не может быть POD печатать только в силу наличия конструктор.) Этот флаг для пользователей кто знает, что они пишут непереносимый код и у кого есть сознательно выбран, чтобы игнорировать предупреждение об этом.

Ограничения на "смещение" могут быть расслаблен в будущей версии C ++ стандарт.

Моя проблема в том, что почти все мои T-типы имеют конструкторы и поэтому классифицируются как не POD. Я проигнорировал этот пункт как не относящийся к делу ранее - и, конечно, он не должен иметь никакого отношения к смещению в принципе. Проблема в том, что в стандарте C ++ используется одна классификация POD и не POD, хотя существует ряд различных способов быть не POD, и компилятор правильно предупреждает о нестандартном использовании по умолчанию.

Мое решение на данный момент будет вариант выше, чтобы подавить предупреждение - теперь мне просто нужно выяснить, как сказать cmake использовать его.

...