Дает ли std::hash одинаковый результат для одного и того же ввода для разных скомпилированных сборок и разных машин?

У меня есть некоторые случайные параметры теста, для которых мне нужно вычислить хэш, чтобы определить, запускался ли я с теми же параметрами. Я мог бы запустить тест, используя тот же исходный код, перекомпилированный в другое время, или запустить его на другой машине.

Тем не менее, я хочу определить, использовались ли те же параметры для запуска. Дает ли std::hash один и тот же результат для одного и того же ввода для разных скомпилированных сборок и разных машин?

e.g.

std::hash<string>{}("TestcaseParamVal0.7Param0.4");

Всегда ли это будет уникальный номер?


person Nelson Pinto    schedule 03.07.2018    source источник
comment
добавлен пример кода   -  person Nelson Pinto    schedule 03.07.2018
comment
@Oighea, не на все вопросы нужен код, и, в частности, на этот вопрос не похоже, чтобы он был ясным и на него можно было ответить.   -  person zneak    schedule 03.07.2018
comment
Дело в том, что исходная форма плохо отформатирована и разбита на абзацы. Вот почему он вспомнил.   -  person Ṃųỻịgǻňạcểơửṩ    schedule 03.07.2018


Ответы (1)


Нет, std::hash не гарантирует, что результат будет одинаковым для разных компьютеров, сборок или даже выполнения одной и той же сборки на одном компьютере. Ваша единственная гарантия заключается в том, что во время одного выполнения одинаковые объекты будут иметь одинаковый хэш. (Конечно, нет никакой гарантии, что неравные объекты будут иметь разные хэши.)

Некоторые реализации изо всех сил стараются изменить результаты хеширования между выполнениями, поскольку это снижает риски отказа в обслуживании из-за низкой производительности хеш-таблиц при наличии множества ключей с одним и тем же хэшем. Это явно разрешено стандартом, который только гарантирует, что результаты непротиворечивы на протяжении всей программы.

Если вам нужна повторяемость между исполнениями и машинами, вы не можете использовать std::hash и должны развернуть свой собственный эквивалент.

person zneak    schedule 03.07.2018
comment
Для лучшей защиты от DoS используйте безопасный криптографический одноразовый номер (некоторые называют его солью) в функции безопасного криптографического хеширования: никто другой (кроме шпионского ПО с полным доступом для чтения на компьютере, на котором запущен сервер) не сможет создать преднамеренные коллизии хэшей. (Для безопасного хэша с одноразовым номером подойдет даже старый добрый MD5.) OTOH, такие хеш-функции намного медленнее, чем некриптографический хэш. - person curiousguy; 03.07.2018
comment
IMO, если это так важно для вас, вы должны использовать контейнер с предсказуемой производительностью (например, std::map) вместо вычисления дорогого хэша и хранения только 8 байтов. - person zneak; 03.07.2018
comment
Хорошая идея, но это не замена: интерфейс другой. Что, если тип имеет только сравнение на равенство и хеш-функцию? - person curiousguy; 03.07.2018
comment
Конечно, вам придется создать свой собственный компаратор, что не намного хуже, чем написание собственной хеш-функции. Использование криптографического хэша для вещей, которые не являются блоками данных, также не всегда просто. - person zneak; 03.07.2018
comment
Да, если нет функции сериализации данных, которая гарантированно будет стабильной, чисто аппликативной (два одинаковых значения объекта получают одинаковую сериализацию), вы правы. И эта сериализация тоже может быть дорогостоящей! - person curiousguy; 03.07.2018
comment
@zneak Что считается казнью? Требуются ли два экземпляра одного и того же std::hash‹T› для получения одного и того же результата, если программа никогда не перезапускается? - person Wei Hsieh; 11.03.2021
comment
@zneak Есть ли у вас какие-нибудь хорошие хэш-функции для использования вместо std::hash, если я хочу получить одинаковые результаты между несколькими запусками? - person Nisal Dissanayake; 08.07.2021