С++. Указатели. Операция delete

126
28 сентября 2019, 17:10

Я начинающий в программировании. Читая книгу о С++ в главе посвященной указателям (в частности оператору delete), я наткнулся на то, что в среде VS2017 после выполнения операции delete к любым указателям, которые не ссылаются на одну переменную, возвращается адрес 00008123. В то время как во многих источниках пишется, что значение указателя не изменяется. С чем это может быть связано? Заранее большое спасибо!

#include "stdafx.h"
#include <iostream>
using namespace std;

int main()
{
  int *p1, *p2;
  p1 = new int;
  p2 = p1;
  cout << p1 << endl;
  delete p1;
  cout << p1 << endl;
  cout << p2 << endl;
  system("pause");
  return 0;
}

Данная программа выведет случайный код при первом выводе p1 и этот же код при выводе p2. А при втором выводе p1 выведет 00008123.

Answer 1

Данное поведение является документированной функцией студии.
Подробнее можно почитать тут:
https://cloudblogs.microsoft.com/microsoftsecure/2012/04/24/guarding-against-re-use-of-stale-object-references/ и тут:
https://docs.microsoft.com/en-us/cpp/build/reference/sdl-enable-additional-security-checks?view=vs-2017
В настройках проекта опция находится тут (студия 2015, в 17й там же по идее):
Properties -> C/C++ -> General -> SDL Checks.
При включении опции изменяется генерируемый студией асм код.

Исходный с++:

int main()
{
    int* p1 { nullptr };
    int* p2 { nullptr };
    p1 = new int;
    p2 = p1;
    cout << "pointer 1:" << p1 << endl;
    cout << "pointer 2:" << p2 << endl;
    delete p1;
    cout << "pointer 1:" << p1 << endl;
    cout << "pointer 2:" << p2 << endl;
    system("pause");
    return 0;
}

С выключенной опцией (дебаг):

    delete p1;
002F2629  mov         eax,dword ptr [p1]  
002F262C  mov         dword ptr [ebp-0ECh],eax  
002F2632  push        4  
002F2634  mov         ecx,dword ptr [ebp-0ECh]  
002F263A  push        ecx  
002F263B  call        operator delete (02F105Ah)  
002F2640  add         esp,8  

(релиз)

    delete p1;
00201060  push        4  
00201062  push        esi  
00201063  call        operator delete (0201443h)  

Вывод:

pointer 1:009C0568
pointer 2:009C0568
pointer 1:009C0568
pointer 2:009C0568 

Со включенной опцией (дебаг):

    delete p1;
00E92629  mov         eax,dword ptr [p1]  
00E9262C  mov         dword ptr [ebp-0ECh],eax  
00E92632  push        4  
00E92634  mov         ecx,dword ptr [ebp-0ECh]  
00E9263A  push        ecx  
00E9263B  call        operator delete (0E9105Ah)  
00E92640  add         esp,8  
00E92643  cmp         dword ptr [ebp-0ECh],0  
00E9264A  jne         main+0F8h (0E92658h)  
00E9264C  mov         dword ptr [ebp-0F4h],0  
00E92656  jmp         main+108h (0E92668h)  
00E92658  mov         dword ptr [p1],8123h  
00E9265F  mov         edx,dword ptr [p1]  
00E92662  mov         dword ptr [ebp-0F4h],edx  

(релиз)

    delete p1;
00D51060  push        4  
00D51062  push        esi  
00D51063  call        operator delete (0D51453h)  
00D51068  add         esp,8  
00D5106B  mov         ecx,8123h  
00D51070  test        esi,esi  
00D51072  mov         eax,esi 

Вывод:

pointer 1:006D0568
pointer 2:006D0568
pointer 1:00008123
pointer 2:006D0568

В то время как во многих источниках пишется, что значение указателя не изменяется. С чем это может быть связано? Заранее большое спасибо!

Доверяйте документации того компилятора, которым пользуетесь.

Answer 2

И утверждение "адрес указателя не изменяется", и утверждение "после выполнения операции delete к любым указателям, которые не ссылаются на одну переменную, возвращается адрес 00008123" является полнейшей бессмыслицей.

Если речь идет о значении (а не "адресе") указателя, к которому была применен оператор delete, то это значение не определено. И это не какая-то теоретическая неопределенность, а вполне практическая оптимизационная возможность, которая может приводить к непредсказуемым изменениям значения указателя после delete.

READ ALSO
Как по очереди анимировать Views

Как по очереди анимировать Views

У меня на странице несколько ViewНужно чтобы каждый анимировался после предыдущей

124
Использование RandomAccessFile, кодировки

Использование RandomAccessFile, кодировки

При чтении байтов из файла с использовании RandomAccessFile нормально выводится в консоль только латиницаЧтоб выводилась нормально кирилица необходимо...

141