NULL포인터 호출문제.....
먼저 간단한 소스를 봐주세요..
class base
{
public:
base() { printf ("construct\n"); };
~base() { printf("desctruct\n"); };
public:
void func() { printf("this %x \n", this); };
}
int main()
{
base aa; // construct 찍힘
base *p = 0;
printf("0x%x \n", p ); // 0x0 찍힘
delete p; // 0번지를 지울려고 했기때문에 segment fualt 가 날것으로 예상하지만 아무변화없음
p++;
printf("0x%x \n", p ); // 0x1 찍힘..
p->func(); // this 0x1 찍힘
base *pp = new base; // construct 찍힘
pp = 0;
pp->func(); //this 0x0 찍힘
delete pp; // desctruct 가 안찍힘..
}
제 생각엔 당연히 null 포인터 호출시 segment fault 가 유발될것으로 생각했는데
이게 무슨 일인가요..
널 포인터를 증가시켜서 호출했더니... 이것도 호출되고.
도움 부탁드립니다..
delete p ->; 0번지를
delete p ->; 0번지를 지우는게 아니고 메모리만 해제함(p는 생성조차 되지 않아서 delete 할 것도 없네요).
p++ ; p 값은 정상적으로 작동함.
base *pp = new base; // construct 찍힘
pp = 0;
-> pp 값을 바꾸었기 때문에 생성되지 않은 객체로서 delete 가 되지 않음.
p->func() 관련해서는...
size가 0인 메모리를 free할 때 library 단에서 아마 무시할겁니다.
p->func() 에서 p가 잘못된 값인데도 동작하는 이유는 func()내에서 dynamic(run-time에 할당되는) object를 사용하지 않기 때문에,
virtual function table 같은 걸 사용하지 않을테고, 결과적으로 C++ 컴파일러가 p->func()를 compile time에
정할 수 있기 때문에 바로 해당 function으로 binding하기 때문일겁니다. ^^
p = 0; delete p; NULL
NULL 포인터를 delete하는 것은 전혀 문제가 없는 것으로 알고 있습니다.
아마 Effective C++에 언급된 것으로 기억이 납니다.
func 함수 내부에서 구조체의 멤버변수에 write하도록 하면 아마 에러가 문제가 발생할 것으로 보입니다.
func은 다음과 같이 호출되겠죠.
하지만 null인 this를 func내부에서 전혀 사용하지 않으니까 문제가 발생하지 않는 것 같습니다.
위와 마찬가지로 null에 대한 delete 호출은 어떠한 일도 하지 않는 것 같습니다.
C++에 익숙하진 않지만..
p->func();
위의 경우 func()가 (가상 함수가 아닌) 일반 함수라면
함수 호출 시점에 p에 대한 접근이 일어나지 않는 것 같습니다.
(p의 타입 정보를 통해 name mangling을 수행하여
compile time에 함수의 주소를 미리 계산해 두고
run time에는 그냥 해당 함수를 호출만 하는 것 같습니다.)
func()를 가상 함수로 선언하면 원하는? 결과를 얻으실 수 있을 듯..
음 이글 보다가 문득 해결되지 못한 문제가 생각나서 질문!
비슷한 문제이긴한데
printf("OK: %p\n", &(*((char*)0)));
printf("Segmentation Fault: %d\n", (*((char*)0)));
첫번째 에서도 똑같이 0를 참조하긴 하니까 오류가 나야하는거 아닌가요?
---------------------------------------------
아치리눅스좀 써주세요
-> 아치리눅스 유저 좀 꼬셔오세요. 1인당 10명!
댓글 달기