Как стать автором
Обновить

Комментарии 39

В свое время разбирался с реализацией методов под gcc для архитектур ARM и AVR. Главный вывод, который я вынес из понятого — нельзя ничего предполагать и, если Вам нужен вызов метода, то единственный надежный способ — шаблоны и явный вызов метода в нужном месте, все остальное — «от лукавого».
А по поводу «страшилок» как нельзя лучше подходит старая фраза «В уставе караульной службы каждая строчка написана кровью военнослужащих, которые пытались делать по своему»
Согласен со всем.
Не понравилось что в страшилке не было описано почему оно так, с чем и пытался разобраться тоже.
С уважением отношусь к Вашим исследованиям, но это только часть айсберга. У каждого компилятора реализация указателей объектов класса отличается. Поэтому нужно аккуратно стрелять из этого оружия. На хабре была отличная статья на эту тему, но к сожалению быстро найти не смог.
Это я согласен
часто имеют размер больше 8 байт.

Вывод: 16
Размер указателя на метод больше 8 байт.

Прежде чем что-то утверждать стоит указать для какой архитектуры компилируется пример, 32 и 64 бит.

16 байт для x86-64
8 байт для x86-32
В статье тоже добавил
Добавил что все для X86-64
Имел в виду, что указатель на метод 16 байт в 64 битах, и 8 байт в 32 битах.
У меня нет технической возможности проверить что происходит в компиляторах Microsoft, поэтому не особо про них рассказал. Однако протестировав онлайн компиляторы, я заметил что MSVC умеет анализировать структуру классов и удалять поле значения корректирования, если оно не требуется.

Нет, MSVC поступает иначе. Я прошу прощения за самоцитирование, но я делал доклад, где было упомянуто сравнение в том числе генерации кода указателя на метод: www.youtube.com/watch?v=Ak0u8PX5tRU (примерно с 15 минут)
(про вышеупомянутые ARM и AVR там тоже есть).
Как бы там ни было, не следует делать никаких предположений о том, что там под капотом, и не выходить за пределы языка.
Зачем ты тогда делал целый доклад про то что под капотом, если не следует делать предположений никаких?
Или смотреть ассемблер — это не предположение (или не под капотом?), а простой примерчик — это предположение о том что под капотом?
Я точно делаю что-то не то?
Иногда приходится читать ассемблер, особенно если имеешь дело с экзотической платформой. Или, куда более редко, писать компилятор или его часть.
С эти сложно поспорить, но как это стыкуется с предыдущими высказываниями?

Может быть устаревшая, но всё равно полезно Указатели на функции-члены и реализация самых быстрых делегатов на С++. Отдельный раздел, дополняющий эту статью на Хабре: "Реализация указателей на функции-члены".

НЛО прилетело и опубликовало эту надпись здесь

Только если вам очень повезет, и указатель на функцию-член действительно будет размером sizeof(void*).


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

НЛО прилетело и опубликовало эту надпись здесь

Адрес чего? Выше вы привели код, из которого можно понять, что там происходит получение значения машинного адреса указателя на указатель на функцию-член класса.


В таком случае указатель на указатель будет действительно sizeof(void*), но это уже следующий уровень косвенности.

НЛО прилетело и опубликовало эту надпись здесь
Я как-то не спорю ни с чем, просто хотел сказать что ассемблер тут не особо нужен вообще впринципе. Есть же надежная функция memcpy)
Ну и си сам по себе хорошо с памятью все достает и кладет. Можно при желании неявно вызвать тот же memcpy без его прямого вызова
НЛО прилетело и опубликовало эту надпись здесь
Я через memcpy все доставал
github.com/wasiher/member_pointers_linux/blob/master/member_pointers_linux.cpp#L11
Сколько знаю, компилятору может быть болезненно работать с ассемблером.
Самое безопасное, наверное, именно чтоб кастами разными приводить.
НЛО прилетело и опубликовало эту надпись здесь
Я однажды гуглил список всех УБ под С++, но не осилил их найти.
Теперь каждый раз когда что-то делаю в С++, узнаю что есть еще УБ где-то почему-то.
УБ похожи на покемонов.
Это точно все?
Например, нельзя иметь бесконечную рекурсию в C++.
Про то что указатель на функцию преобразовывать в void* тоже не очень законно тут тоже не вижу.
Или это + дока по си должны все закрыть?
Я согласен с несогласием, но про отладочную информацию это для красного словца было сказано или реально что-то такое есть?

Доказательств привести не могу, но теоретически оптимизатор может знать реальный адрес функции после девиртуализации какого-то экземпляра класса или link-time optimization.

Адреса членов-функций и членов-данных объекта класса вычисляются (если правильно помню) как смещение от указателя на объект this.
Ещё не рассмотрен случай виртуального наследования. Думаю, размер указателя ещё подрастёт.
Что-то я пробовал. Не особо росло в случае clang и gcc.
Если сможешь что-то нашаманить и скинуть, то буду рад.
Если брать указатель на неизвестную структуру, то в gcc и clang будет 16.
gcc: rextester.com/CUCL60020
clang: rextester.com/ZCB93726
Если брать msvc, мало понимаю что там и почему происходит. Там размер 24, и что-то может и есть.
msvc: rextester.com/SNU4983
Может, если будет не лень, могу попробовать разобраться что происходит в MSVC, если кому надо…
Я что-то вообще не понял, что у тебя за примеры. Там указатель на необъявленный класс везде. Я видел очень давно статью на RSDN, кажется, возможно переводную, где все эти вопросы очень подробно разобраны.
Ну подумай. Что может быть более неопределенное, чем указатель на необъявленный класс? И в каком случае компилятор не может делать предположения относительно стуктуры класса совсем?
Указатель на необъявленный класс — это максимальный размер. Или ошибаюсь?
Если мне память не изменяет, в той статье было написано, что некоторые компиляторы делают рискованную оптимизацию для необъявленных классов.
Вот тут я нашёл кусок статьи, которая рассматривает вопрос подробнее, чем твоя stackoverflow.com/a/13875868/8452129
Видел эту статью из 2003 года. Пришлось разбираться самому, потому что из кода видно только то что sizeof указателя на метод больше обычного указателя.

Насколько я понимаю, gcc и clang всегда используют минимум 2 слова, msvc пытается варьировать 1-3 слова, в зависимости от класса. Реймонд Чен писало про это: Pointers to member functions are very strange animals

gcc и clang всегда размером с 2 указателя
msvc как понял: 1 указатель + 3 32битных инта (ну и компиль обрубает эти инты, если не нужны по какой-то причине)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации