#cpp #указатели #delete
Я начинающий в программировании. Читая книгу о С++ в главе посвященной указателям (в частности оператору delete), я наткнулся на то, что в среде VS2017 после выполнения операции delete к любым указателям, которые не ссылаются на одну переменную, возвращается адрес 00008123. В то время как во многих источниках пишется, что значение указателя не изменяется. С чем это может быть связано? Заранее большое спасибо! #include "stdafx.h" #includeusing 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.
Ответы
Ответ 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 В то время как во многих источниках пишется, что значение указателя не изменяется. С чем это может быть связано? Заранее большое спасибо! Доверяйте документации того компилятора, которым пользуетесь.Ответ 2
И утверждение "адрес указателя не изменяется", и утверждение "после выполнения операции delete к любым указателям, которые не ссылаются на одну переменную, возвращается адрес 00008123" является полнейшей бессмыслицей. Если речь идет о значении (а не "адресе") указателя, к которому была применен оператор delete, то это значение не определено. И это не какая-то теоретическая неопределенность, а вполне практическая оптимизационная возможность, которая может приводить к непредсказуемым изменениям значения указателя после delete.
Комментариев нет:
Отправить комментарий