Visual Studio는 삭제 된 포인터로 무엇을하며 그 이유는 무엇입니까?
필자가 읽은 C ++ 책은 포인터를 delete
연산자를 사용하여 삭제하면 가리키는 위치의 메모리가 "해제"되어 덮어 쓸 수 있다고 말합니다. 또한 포인터가 다시 할당되거나로 설정 될 때까지 동일한 위치를 계속 가리 킵니다 NULL
.
그러나 Visual Studio 2012에서는; 이것은 사실이 아닌 것 같습니다!
예:
#include <iostream>
using namespace std;
int main()
{
int* ptr = new int;
cout << "ptr = " << ptr << endl;
delete ptr;
cout << "ptr = " << ptr << endl;
system("pause");
return 0;
}
이 프로그램을 컴파일하고 실행하면 다음과 같은 결과가 나타납니다.
ptr = 0050BC10
ptr = 00008123
Press any key to continue....
delete가 호출 될 때 포인터가 가리키는 주소는 분명히 변경됩니다!
왜 이런 일이 발생합니까? 이것은 Visual Studio와 관련이 있습니까?
그리고 delete가 어쨌든 가리키는 주소를 변경할 수 있다면 왜 NULL
임의의 주소 대신 포인터를 자동으로 설정하지 않습니까?
저장된 주소 ptr
가 항상 덮어 쓰여지는 것을 알았 습니다 00008123
...
이것은 이상하게 보였으므로 약간의 파고를했고 "C ++ 객체를 삭제할 때 자동 포인터 삭제"에 대해 설명하는 섹션이 포함 된 이 Microsoft 블로그 게시물 을 찾았 습니다 .
... NULL 검사는 공통 코드 구성을 의미합니다. 기존의 NULL 검사는 살균 값으로 NULL을 사용하는 것과 결합하여 근본 원인을 해결해야하는 실제 메모리 안전 문제를 숨길 수 있습니다.
이러한 이유로 우리는 살균 값으로 0x8123을 선택했습니다. 운영 체제 관점에서 이것은 제로 주소 (NULL)와 동일한 메모리 페이지에 있지만 0x8123에서의 액세스 위반은보다 세심한주의가 필요하므로 개발자에게 더 잘 드러날 것입니다. .
Visual Studio가 포인터를 삭제 한 후 포인터로 수행하는 작업을 설명 할뿐만 아니라 NULL
자동으로 설정하지 않기로 선택한 이유에 대한 답변도 제공합니다 .
이 "기능"은 "SDL 검사"설정의 일부로 활성화됩니다. 활성화 / 비활성화하려면 PROJECT-> 속성-> 구성 속성-> C / C ++-> 일반-> SDL 검사로 이동하십시오.
이를 확인하려면 다음을 수행하십시오.
이 설정을 변경하고 동일한 코드를 다시 실행하면 다음과 같은 출력이 생성됩니다.
ptr = 007CBC10
ptr = 007CBC10
"기능"은 살균 삭제를 호출, 같은 위치에 두 개의 포인터를 가지고 있기 때문에 경우에 따옴표에 하나 그들 중입니다. 다른 하나는 유효하지 않은 위치를 가리키고 있습니다.
Visual Studio는이 결함을 디자인에 문서화하지 못하여 끈적 끈적한 상황에 대비할 수 있습니다.
/sdl
컴파일 옵션의 부작용이 나타납니다 . VS2015 프로젝트에 대해 기본적으로 켜져 있으며 / gs에서 제공하는 것 이외의 추가 보안 검사가 가능합니다. 프로젝트> 속성> C / C ++> 일반> SDL 검사 설정을 사용하여 변경하십시오.
MSDN 기사 에서 인용 :
- 제한된 포인터 살균을 수행합니다. 역 참조를 포함하지 않는 표현식과 사용자 정의 소멸자가없는 유형에서는 포인터 호출이 삭제 호출 후 유효하지 않은 주소로 설정됩니다. 이로 인해 오래된 포인터 참조가 재사용되지 않습니다.
삭제 된 포인터를 NULL로 설정하는 것은 MSVC를 사용할 때 좋지 않은 방법입니다. 디버그 힙과이 / sdl 옵션 모두에서 얻는 도움말을 무시하므로 더 이상 프로그램에서 유효하지 않은 비어있는 / 삭제 호출을 감지 할 수 없습니다.
또한 포인터가 재 할당되거나 NULL로 설정 될 때까지 포인터가 계속 동일한 위치를 가리킬 것입니다.
그것은 확실히 잘못된 정보입니다.
delete가 호출 될 때 포인터가 가리키는 주소는 분명히 변경됩니다!
왜 이런 일이 발생합니까? 이것은 Visual Studio와 관련이 있습니까?
This is clearly within the language specifications. ptr
is not valid after the call to delete
. Using ptr
after it has been delete
d is cause for undefined behavior. Don't do it. The run time environment is free to do whatever it wants to with ptr
after the call to delete
.
And if delete can change the address it is pointing to anyways, why wouldn't delete automatically set the pointer to NULL instead of some random address???
Changing the value of the pointer to any old value is within the language specification. As far as changing it to NULL, I would say, that would be bad. The program would behave in a more sane manner if the value of the pointer were set to NULL. However, that will hide the problem. When the program is compiled with different optimization settings or ported to a different environment, the problem will likely show up in the most inopportune moment.
delete ptr;
cout << "ptr = " << ptr << endl;
In general even reading (like you do above, note: this is different from dereferencing) values of invalid pointers (pointer becomes invalid for example when you delete
it) is implementation defined behaviour. This was introduced in CWG #1438. See also here.
Please note that before that reading values of invalid pointers was undefined behaviour, so what you have above would be undefined behaviour, which means anything could happen.
I believe, you are running some sort of debug mode and VS is attempting to repoint your pointer to some known location, so that further attempt to dereference it could be traced and reported. Try compiling/running the same program in release mode.
Pointers are usually not changed inside delete
for the sake of efficiency and to avoid giving a false idea of safety. Setting delete pointer to pre-defined value will do no good in most of complex scenarios, since the pointer being deleted is likely to be only one of several pointing to this location.
As a matter of fact, the more I think about it, the more I find that VS is at fault when doing so, as usual. What if the pointer is const? Is it still gonna change it?
After deleting the pointer the memory to which it points may still be valid. To manifest this error, the pointer value is set to an obvious value. This really helps the debugging process. If the value were set to NULL
, it may never show up as potential bug in the program flow. So it may hide a bug when you test later against NULL
.
Another point is, that some run time optimizer may check that value and change its results.
In earlier times MS set the value to 0xcfffffff
.
'IT' 카테고리의 다른 글
Python 스크립트에서 POST를 사용하여 파일 보내기 (0) | 2020.07.05 |
---|---|
적절한 Linq where 절 (0) | 2020.07.05 |
각 제품에 많은 매개 변수가있는 여러 종류의 제품에 대한 제품 테이블을 디자인하는 방법 (0) | 2020.07.05 |
webpack.config.js 파일 인 angular-cli-새로운 angular6는 ng eject를 지원하지 않습니다 (0) | 2020.07.05 |
자바 스크립트와 스레드 (0) | 2020.07.05 |