Могу ли я использовать адрес argc в main как случайный источник?

Я хочу создать программу, которой нужно только одно случайное число, поэтому я пытаюсь использовать адрес argc в основной функции в качестве случайного источника, потому что я думаю, что расположение программы в памяти является случайным, а также она может сохранять некоторые операторы включения, поэтому я попробовал:

#include <stdio.h>
int main(int argc,const char* argv[]){
    printf("%lu\n",(unsigned long int)&argv/sizeof(unsigned long int));
    return 0;
}

но я обнаружил, что вывод в каждый раз не очень "случайный": они кратны 4:

17591828907268
17591841542404
17591845040388
17591834556676

Какова причина? И возможно ли использование адреса argc в качестве случайного числа?

Затем я пытаюсь удалить некоторые биты адреса:

#include <stdio.h>
int main(int argc,const char* argv[]){
    printf("%lu\n",(unsigned long int)&argv >> 12);
    return 0;
}

на этот раз он выглядит довольно случайным, по крайней мере, у него есть как нечетные, так и четные числа:

34359070631
34359034616
34359078055
34359080624

это "правильный" способ превратить адрес argc в случайное число?

3 ответа

Решение

Какова причина?

Требования выравнивания для вашей архитектуры, которые я предполагаю, x86 и int 4 байта, что означает каждый int должен быть выровнен по адресу, который делится на 4 (это именно то поведение, которое вы видите).

И возможно ли использование адреса argc в качестве случайного числа?

Возможный? Да, конечно. Вы просто идете и делаете это.

Это хорошая идея? Нет, определенно нет. Смотрите ниже, почему.

Это "правильный" способ превратить адрес argc в случайное число?

Я предполагаю, что под "правильным" вы подразумеваете хороший источник энтропии, и ответ на этот вопрос - нет.

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

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

Если вам действительно нужна случайность, вы должны использовать одно из:

  1. / DEV / случайное
  2. / DEV / urandom

    Для информации об этих двух см. Как использовать / dev/random или urandom в C?

  3. srand()

    Информация о посеве srand() находится здесь: Рекомендуемый способ инициализации srand?

  4. Внешняя библиотека, специально предназначенная для этого.

    Некоторая информация здесь Хороший генератор случайных чисел для C

Это кратно 4, потому что адреса функций будут выровнены по словам на каждой платформе, о которой я знаю (я предполагаю, что это x86 или x86_64?)

Адрес argc может быть "случайным" для некоторого смысла слова, в том смысле, что вы, вероятно, не будете знать, что это такое, поэтому, если вы используете это, чтобы заполнить начальные условия для игры или что-то, что, вероятно, будет работать; определенно не полагайтесь на это, если вы используете это для шифрования или чего-то еще - злоумышленник может сделать что-то, чтобы повлиять на загрузку argc.

Тем не менее, ваша библиотека C поставляется с прекрасно работающими функциями rand() и srand(), которые в качестве бонуса позволяют вам преднамеренно заполнить ее определенным значением, которое может быть очень полезно при отладке; Я придерживаюсь этого, когда мне нужны случайные числа, лично.

Другие вопросы по тегам