Получение адреса объекта по адресу члена этого объекта
От: maks1180  
Дата: 10.12.22 17:20
Оценка:
Мне нужно получить адреса объекта по адресу члена этого объекта. Планирую это делать через offsetof.
1) Есть ли другие способы ?
2) Я не совсем понял в описании кажется, что с ним будут проблемы в C23 ? Насколько надёжно и правильное это решение ?
3) gcc генерирует warning если в классе есть виртуальные функции. Но код генерирует правильный с учётом указателя на v-table. В чём тут дело ?

// gcc v4.8 Linux
warning: invalid access to non-static data member ‘MyClass::a’ of NULL object

// gcc v10.2 Windows
warning: 'offsetof' within non-standard-layout type 'MyClass' is conditionally-supported [-Winvalid-offsetof]


printf("%u \n", offsetof(MyClass, a));

class MyClass {
public:
virtual void Test1() {};
UPTR a;
int b;
int c;
};
===============================================
(реклама, удалена модератором)
Отредактировано 10.12.2022 17:22 maks1180 . Предыдущая версия .
Re: Получение адреса объекта по адресу члена этого объекта
От: _NN_ www.nemerleweb.com
Дата: 10.12.22 21:04
Оценка:
Здравствуйте, maks1180, Вы писали:

M>Мне нужно получить адреса объекта по адресу члена этого объекта. Планирую это делать через offsetof.

M>1) Есть ли другие способы ?
M>2) Я не совсем понял в описании кажется, что с ним будут проблемы в C23 ? Насколько надёжно и правильное это решение ?
M>3) gcc генерирует warning если в классе есть виртуальные функции. Но код генерирует правильный с учётом указателя на v-table. В чём тут дело ?

Макрос offsetof работает в классах со стандартной разметкой.
При добавлении виртуальных функций, а ещё с возможностью множественного наследования компилятору сложно определить, что вам нужно

Начиная с C++17 компилятор [url-https://en.cppreference.com/w/cpp/types/offsetof]может, но не обязан,[/url] поддерживать для классов с виртуальной таблицей.

Как мне кажется лучшим вариантом будет найти способ убрать виртуальную функцию где требуется offsetof.
Или пользоваться только компиляторами поддерживающими данную функциональность если нет другого варианта.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Получение адреса объекта по адресу члена этого объекта
От: maks1180  
Дата: 11.12.22 06:47
Оценка:
M>>Мне нужно получить адреса объекта по адресу члена этого объекта. Планирую это делать через offsetof.
M>>1) Есть ли другие способы ?
M>>2) Я не совсем понял в описании кажется, что с ним будут проблемы в C23 ? Насколько надёжно и правильное это решение ?
M>>3) gcc генерирует warning если в классе есть виртуальные функции. Но код генерирует правильный с учётом указателя на v-table. В чём тут дело ?

_NN>Макрос offsetof работает в классах со стандартной разметкой.

_NN>При добавлении виртуальных функций, а ещё с возможностью множественного наследования компилятору сложно определить, что вам нужно

Я не пойму в чём проблема если у класса есть фиртуальная функция? разница лишь только в том, что в начале класса добавляется указатель на v-table, все переменные класса сдвигаются на размер указателя.
===============================================
(реклама, удалена модератором)
Re: Получение адреса объекта по адресу члена этого объекта
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.12.22 11:51
Оценка:
Здравствуйте, maks1180, Вы писали:

M>Мне нужно получить адреса объекта по адресу члена этого объекта.


Из-за чего такое извращение?
Re[2]: Получение адреса объекта по адресу члена этого объекта
От: kov_serg Россия  
Дата: 11.12.22 12:56
Оценка: -1
Здравствуйте, Евгений Музыченко, Вы писали:

M>>Мне нужно получить адреса объекта по адресу члена этого объекта.


ЕМ>Из-за чего такое извращение?

Такое извращение используется в ядре линукса и считается нормой.
В С++ такое можно использовать только к POD структурам, что бы не связывать руки компилятору в его сомнительных оптимизациях.
Re[3]: Получение адреса объекта по адресу члена этого объект
От: okman Беларусь https://searchinform.ru/
Дата: 11.12.22 13:22
Оценка:
Здравствуйте, maks1180, Вы писали:

M>Я не пойму в чём проблема если у класса есть фиртуальная функция? разница лишь только в том, что в начале класса добавляется указатель на v-table, все переменные класса сдвигаются на размер указателя.


Есть некоторые кейсы, при которых offsetof не может корректно отработать. Сразу приходит на ум виртуальное наследование.
Да, это экзотика, которая редко встречается, но это вполне легальная часть C++. И компиляторы обычно ругаются на попытку применить offsetof к таким классам.
Можно придумать примерно такой кейс:
#include <cstdio>

struct Base
{
    virtual ~Base() {}
    int m_val;
};

struct Left : virtual Base
{
    void showOffset()
    {
        printf("%zu\n", (size_t)&m_val - (size_t)this);
    }
};

struct Right : virtual Base
{
};

struct Child : Left, Right
{
};

int main()
{
    Left left;
    left.showOffset();
    
    Child child;
    child.showOffset();
    
    return 0;
}

Clang и GCC выводят 16 и 24. MSVC — 8 и 12. Ну т.е. offset от 'Left' до 'm_val' здесь зависит от того, как класс Left
включен в наследование — при виртуальном наследовании эта информация должна вычисляться динамически, т.е. в рантайме.
Отредактировано 11.12.2022 13:23 okman . Предыдущая версия .
Re[3]: Получение адреса объекта по адресу члена этого объекта
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.12.22 15:03
Оценка: +2
Здравствуйте, kov_serg, Вы писали:

_>Такое извращение используется в ядре линукса и считается нормой.


Это может быть нормой по отношению к структуре, но не объекту. Поскольку в ядре Linux нет кода на C++, то и объектов в обсуждаемом смысле тоже нет.

_>В С++ такое можно использовать только к POD структурам, что бы не связывать руки компилятору в его сомнительных оптимизациях.


К объектам это не должно применяться прежде всего потому, что в С++ такие операции делаются по-другому.
Re[4]: Получение адреса объекта по адресу члена этого объекта
От: kov_serg Россия  
Дата: 11.12.22 15:31
Оценка: -1
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>К объектам это не должно применяться прежде всего потому, что в С++ такие операции делаются по-другому.

Так я и не спорю. В C++ многое через одно место сделано.
Re[5]: Получение адреса объекта по адресу члена этого объекта
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.12.22 15:39
Оценка:
Здравствуйте, kov_serg, Вы писали:

ЕМ>>К объектам это не должно применяться прежде всего потому, что в С++ такие операции делаются по-другому.


_>В C++ многое через одно место сделано.


Хм, что именно в C++ сделано "через одно место" применительно к данному вопросу?
Re[6]: Получение адреса объекта по адресу члена этого объекта
От: kov_serg Россия  
Дата: 11.12.22 17:35
Оценка: -1
Здравствуйте, Евгений Музыченко, Вы писали:

_>>В C++ многое через одно место сделано.

ЕМ>Хм, что именно в C++ сделано "через одно место" применительно к данному вопросу?
Многое. Например: объявление приватных членов классов в заголовочных файлах.
указатели, на замыкания, на виртуальные методы, на поля класса, битовые поля.
сокрытие реализации там где не надо, но при этом выворачивание наружу костылей компилятора
Re[7]: Получение адреса объекта по адресу члена этого объекта
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.12.22 17:59
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Например: объявление приватных членов классов в заголовочных файлах.


Какое это имеет отношение к C++? Традиционный компилятор C++ вообще ничего не знает о "заголовочных файлах", он тупо обрабатывает файлы, поданные ему на вход. А уж как там организованы объявления/определения — дело программиста.

_>указатели, на замыкания, на виртуальные методы, на поля класса, битовые поля.


Где в C++ указатели на битовые поля, и в чем проблема с остальным?
Re[8]: Получение адреса объекта по адресу члена этого объекта
От: kov_serg Россия  
Дата: 11.12.22 19:07
Оценка: -1
Здравствуйте, Евгений Музыченко, Вы писали:

_>>Например: объявление приватных членов классов в заголовочных файлах.

ЕМ>вообще ничего не знает о "заголовочных файлах"
Ну ну.

_>>указатели, на замыкания, на виртуальные методы, на поля класса, битовые поля.


ЕМ>Где в C++ указатели на битовые поля, и в чем проблема с остальным?

Нет единообразия каждый раз изобретают новые костыли.
Re[9]: Получение адреса объекта по адресу члена этого объекта
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.12.22 19:29
Оценка:
Здравствуйте, kov_serg, Вы писали:

ЕМ>>вообще ничего не знает о "заголовочных файлах"

_>Ну ну.

Так что он, по-Вашему, знает о них?

_>Нет единообразия каждый раз изобретают новые костыли.


Что единообразия нет — согласен. А костыли последние лет десять изобретают в основном для "метапрограммирования", которое в С++ давно пошло вразнос.
Re[10]: Получение адреса объекта по адресу члена этого объекта
От: kov_serg Россия  
Дата: 11.12.22 19:32
Оценка: -1
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Так что он, по-Вашему, знает о них?

precompiled headers

_>>Нет единообразия каждый раз изобретают новые костыли.

ЕМ>Что единообразия нет — согласен. А костыли последние лет десять изобретают в основном для "метапрограммирования", которое в С++ давно пошло вразнос.
Так оно поэтому в разнос и идёт.
Re[11]: Получение адреса объекта по адресу члена этого объекта
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.12.22 20:16
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>precompiled headers


Это не входит в спецификацию языка, не является обязательным к реализации в компиляторе, и не влияет на его логику по отношению к программе.
Re[12]: Получение адреса объекта по адресу члена этого объек
От: kov_serg Россия  
Дата: 12.12.22 06:35
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

_>>precompiled headers

ЕМ>Это не входит в спецификацию языка, не является обязательным к реализации в компиляторе, и не влияет на его логику по отношению к программе.
Это очень печально что такие важные темы не входят в спецификацию. Тем не менее объявление приватных членов класса в том виде что есть в c++ это грандиозный факап, который был заложен изначально и никто исправлять это даже не планирует. Более того любой фанат c++ так же как и вы будет тыкать в стандарт и не понимать о чем речь.
Отредактировано 12.12.2022 6:37 kov_serg . Предыдущая версия .
Re[13]: Получение адреса объекта по адресу члена этого объек
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 12.12.22 09:17
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Это очень печально что такие важные темы не входят в спецификацию.


Что именно Вы считаете важным? Операция #include, что в C, что в C++, тупо вставляет вместо себя какой-то файл, и не более того. У нее нет иного назначения, кроме как позволить собрать текст, подлежащий обработке компилятором, из нескольких файлов вместо одного. Понятие "заголовочный файл" — просто соглашение, традиция, как и использование для него расширения ".h". С тем же успехом в основном файле (.c/.cpp) может быть только определение самого класса, а #include может использоваться для включения определений методов из других файлов.

Если хочется установить для этих файлов другие функции и порядки — нужны и другие языковые средства, вроде модулей.

_>объявление приватных членов класса в том виде что есть в c++ это грандиозный факап, который был заложен изначально и никто исправлять это даже не планирует.


С какой целью его следовало бы исправлять? Это не обязанность, а право программиста. Если он делает простую короткоживущую программу, в этом нет никакой опасности. Если он делает сложную программу, которую долго будут сопровождать другие, то может использовать соответствующие языковые средства.

Исправлять имеет смысл то, что невозможно (или слишком сложно) обойти. Вы еще предложите убрать из C++ reinterpret_cast, function-style и C-style cast.

_>любой фанат c++ так же как и вы будет тыкать в стандарт и не понимать о чем речь.


Я ни разу не фанат ни C, ни C++, к обоим у меня куча претензий на протяжении десятков лет. Но пока C++, с учетом опыта и привычки, для моих задач остается наименьшим злом, а использование для этих задач других языков создаст мне еще больший геморрой.
Re[4]: Получение адреса объекта по адресу члена этого объекта
От: rg45 СССР  
Дата: 15.12.22 12:24
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

M>Мне нужно получить адреса объекта по адресу члена этого объекта


_>>Такое извращение используется в ядре линукса и считается нормой.


ЕМ>Это может быть нормой по отношению к структуре, но не объекту.


А что такое адрес структуры?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: Получение адреса объекта по адресу члена этого объекта
От: σ  
Дата: 15.12.22 12:46
Оценка:
M>Мне нужно получить адреса объекта по адресу члена этого объекта. Планирую это делать через offsetof.
M>1) Есть ли другие способы ?
Без UB способов нет, хоть с vtable, хоть без 🤡
Re: Получение адреса объекта по адресу члена этого объекта
От: Wawan Россия http://www.wawan.ru/resume
Дата: 15.12.22 15:52
Оценка: -2 :))
кастуй этот указатель в указатель на класс,
вызывай любой виртуальный метод класса который вернет заведомо известный тебе результат, сравнивай её результат с образцом,
оберни этот код try-catch для ловли исключений, в случае если произошло исключение сдвинь указатель еще на пару байт,
и так в цикле пока не получишь правильный результат от функции
таков путь
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.