Конфликтующие выходы, когда значение, на которое ссылается указатель, больше не существует

0
#include<iostream.h>
#include<conio.h>
int *p;
void Set()
{
   int i;
   i=7;
   p=&i;
}
int Use()  
{
   double d;
   d=3.0;
   d+=*p;
//if i replace the above 3 statements with --> double d=3.0+*p; then output is 10          otherwise the output is some random value(address of random memory location)
//why is this happening? Isn't it the same? 
   return d;
}
void main()
{
   clrscr();
   Set();
   cout<<Use();
   getch();
}

Мой вопрос, как упоминалось в комментариях выше. Я хочу знать точную причину разницы в выводах. В приведенном выше выходном коде есть какой-то адрес случайной ячейки памяти, и я понимаю, что из-за я является локальной переменной Set() но тогда как это видно во втором случае, заменив его двойным d = 3. 0+ * p; потому что тогда выход приходит 10 (7 + 3), хотя 7 не должно было быть видимым?

  • 0
    У тебя случайно есть клавиша TAB на клавиатуре?
  • 4
    Также нет разумного объяснения необоснованному. UB - это UB.
Показать ещё 4 комментария
Теги:
pointers
function

2 ответа

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

Результат использования указателя p не определен, он также может дать вам segfault или просто вернуть 42. Техническая причина результатов, которые вы получаете, вероятно:

  • i внутри Set помещается в стек. Значение 7 хранится там, и p указывает на это место в памяти. Когда вы вернетесь из значения Set остается в памяти: стек не "уничтожен", это просто указатель стека, который сбрасывается. p все еще указывает на это местоположение, которое по-прежнему содержит целочисленное представление "3".

  • Внутри Use то же место в стеке, которое используется повторно для d.

  • Когда компилятор не оптимизирует, в первом случае (т.е. Все вычисления в одной строке) он сначала использует значение 7 (которое все еще присутствует в памяти с p указывающим на него), выполняет ли вычисление, перезаписывает значение (поскольку вы назначаете его d который находится в том же месте) и возвращает его.

  • Во втором случае он сначала перезаписывает значение с двойным значением 3.0, а затем берет первые 4 байта, которые интерпретируются как целочисленные значения для оценки *p в d+=*p.

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

Это относится ко всем типам "неопределенного поведения", особенно на языках "низкого уровня", таких как C/C++. Плохо то, что "undefined" может очень хорошо означать "отлично работать, пока он не станет слишком поздно"...

0

После выхода из функции Установить значение указателя p становится недействительным из-за уничтожения локальной переменной i. Программа имеет неопределенное поведение.

  • 0
    это моя точка зрения. Если я уничтожен, то почему double d = 3.0 + * p; дает вывод 10?

Ещё вопросы

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