Подтвердить что ты не робот

Адрес переменной необходимо загрузить в память?

У меня проблема - со следующим кодом я пытаюсь выяснить, что хранится на определенном адресе, и как долго моя статическая переменная хранится в этой конкретной позиции. (Я читал, что статические переменные хранятся бесконечно и были весьма удивлены - хотели проверить, было ли это правдой). Код определяет статическую переменную (ее адрес в моей системе равен 0x1000020c0 - это, вероятно, довольно случайный, но он всегда был случайным)

Если теперь я хочу узнать, какое целочисленное значение хранится по этому адресу, я должен сначала распечатать адрес с помощью $number, который затем дает 0x1000020c0. Повторное или повторное толкование адреса (0x1000020c0) дает только 100! если адрес был напечатан до или если я использую & number в повторной интерпретации/переработке.

Может кто-нибудь объяснить, почему это так?

int static number = 100;  

//  std::cout << number << std::endl; <- prints 100

//  prints 100 and the address 0x1000020c0 in my case
//  std::cout << number << " " << &number << std::endl;

//  this does not work unless &number is printed previously
//  std::cout << "Value is :  " << *reinterpret_cast<int*>(0x1000020c0) << std::endl;

// this does work and show the correct value (100)
std::cout << "Value is :  " << *reinterpret_cast<int*>(&number) << std::endl;
4b9b3361

Ответ 1

В любой заданной программе объект может или не может быть сохранен в адресе 0x1000020c0. Нет никаких гарантий в любом случае. Адрес объекта определяется при компиляции (или, возможно, по ссылке) времени. Изменение программы может изменить адрес.

Если вы никогда не берете адрес локального статического объекта и никогда не изменяете его, компилятор может оптимизировать переменную, чтобы память не использовалась. Если объект вообще не существует, то он определенно не существует в ячейке памяти 0x1000020c0.

Если вы используете объект таким образом, чтобы объект существовал, он будет находиться в некоторой ячейке памяти. Принятие адреса объекта обычно вызывает такое требование. Это поразительно похоже на эффект наблюдателя в физике.

Если вы разыщите указатель, который не указывает на объект (соответствующего типа), поведение undefined.


когда я печатаю recast/reinterpret значение, которое находится на 0x1000020c0, оно ничего не печатает

Как я объяснил выше, объект не гарантированно существует в ячейке памяти 0x1000020c0.

хотя объект использовался, так как я напечатал его значение через std:: cout < число;

Доступ к значению объекта необязательно требует, чтобы объект существовал. Компилятор может доказать, что значение объекта равно 100, поэтому оно может хранить это значение как константу, а не хранить статический объект вообще.

Кроме того, даже если статический объект действительно существует, он не обязательно будет существовать в адресе 0x1000020c0, если вы не возьмете адрес и не заметите его.


Как следствие: никогда не добавляйте произвольное число в указатель (если вы не работаете на какой-либо встроенной платформе с жестко привязанной памятью). Видя, что адрес объекта в одной программе равен 0x1000020c0, не делает 0x1000020c0 не произвольным в другой программе.

Ответ 2

  • Предполагая, что конкретный адрес номера - не самая лучшая идея.
  • В С++, static внутри тела функции создается при первом вызове или когда первый раз поток программ С++ встречает переменную. Они никогда не создаются, если не используются.
  • Если возможно, компилятор может выбрать оптимизацию static и заменить его значением.

Ответ 3

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

Статическая переменная не сохраняется "бесконечно"; он хранится в этом месте на время выполнения программы. Если вы работаете на встроенной платформе, где ваш код перескакивает на main() при включении питания, у вас нет ничего другого, что может мешать. Если вы работаете на любой другой платформе (Windows, Linux или любой другой), это место становится бесплатным после завершения программы и сразу же доступно для чего-либо еще.

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

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

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

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