Преобразование адреса функции в 64-разрядное целое число: не определено / плохо себя ведет?

0

Предпосылки: У меня есть сценарий, в котором я должен допускать сравнение между двумя объектами-функторами, используя уникальный идентификатор для проверки, являются ли они равными (я не могу просто проверить, совпадают ли их адреса, поскольку сами указатели функций не являются хранится в объекте). Первоначально у меня была эта идея, чтобы просто запустить генератор id с 0 и увеличить до бесконечности:

struct GenerateUniqueID{
    static std::size_t id_count = 0;

    auto operator()() -> std::size_t { return (id_count++); }
};

... Тем не менее, поскольку у меня буквально тысячи и тысячи этих объектов создавались каждые несколько секунд, мне действительно удалось столкнуться с тем, что id_count переполнен до 0! Результаты были... неприятными. Теперь вторая идея заключалась в том, что, поскольку эти функторы, очевидно, обертывают вокруг функции, я мог бы выполнить сравнение, преобразовывая адрес указателя функции в 64-разрядное целое и сохраняя это в классе для сравнения, Видеть:

//psuedocode
struct Functor{
    std::uint64_t id;

    auto generate_id_from_function_address(function f) -> void {
        id = reinterpret_cast<std::uint64_t>(&f);
    }
};

Теперь, моя забота здесь проста: отличает ли указатели функций от 64-битных целых чисел неуправляемыми/неопределенными? На 32-битных архитектурах? На 64-битных архитектурах? На обоих? Моя главная проблема здесь в том, что с виртуальными функциями, поскольку я знаю, что для встроенных функций компилятор просто создает не-встроенную версию, поэтому там нет проблем.

  • 6
    Вы думаете, что переполнили 64-битный счетчик? При 4 миллиардах приращений в секунду это займет более века ...
  • 0
    converting the address of the function pointer into a 64-bit integer, and storing that in the class for comparison Почему бы не сохранить действительный указатель на функцию?
Показать ещё 15 комментариев
Теги:
undefined-behavior

1 ответ

2
Лучший ответ

Преобразование обычного указателя (не говоря уже о указателе функции) в uint64_t определяется реализацией, поскольку указатели могут быть более широкими, чем 64 бита. Преобразование корректно определено, если вы используете uintptr_t (и этот тип существует).

Преобразование указателя функции в любой целочисленный тип определяется реализацией (даже если вы используете uintptr_t), поскольку указатели на функции могут быть более широкими, чем обычные указатели. Некоторые другие стандарты, такие как POSIX, явно разрешают это, поэтому в POSIX безопасно uintptr_t указатели на указатели данных, такие как void* и uintptr_t.

(Преобразование указателя в элемент с целым числом, указателем данных или указателем регулярной функции не определено и на практике, вероятно, всегда будет терпеть неудачу, так как они больше обычных указателей.)

Тем не менее, может быть проще просто использовать uint64_t вместо size_t для ваших уникальных идентификаторов. В принципе невозможно uint64_t, увеличивая его количество из-за их огромного диапазона.

  • 0
    Так что мои подозрения верны. Благодарю.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню