free 에러 문제
글쓴이: bluebear2706 / 작성시간: 화, 2014/02/04 - 10:52오전
int main(void){
Data_b* data_b = NULL;
Data_a* data_a = NULL;
CreateDataA(&data_a);
CreateDataB(&data_b, &data_a);
printf("1 wrappedkey = %p, pData = %p\n", data_a, data_a->pData);
printf("1 data_b = %p, pData = %p\n", data_b, data_b->pData);
Data_b_Release(data_b);
Data_a_Release(data_a);
printf("1 wrappedkey = %p, pData = %p\n", data_a, data_a->pData);
printf("1 data_b = %p, pData = %p\n", data_b, data_b->pData);
return 0;
}
Forums:
포인터 변수들은 주소값을 담고 있는 변수에
포인터 변수들은 주소값을 담고 있는 변수에 불과합니다.
복사된 변수값은 한쪽이 변해도 안변하죠.
int a = 5;
int b = 0;
b = a;
a = 9;
이렇게 해도 b는 여전히 5를 가집니다. 포인터 변수도 마찬가지입니다.
무언가 알아서 잘 좀 해줬으면 싶지만, 그렇지 못하죠.
이미 free된 메모리 주소값을 담고 있는 포인터 변수가 되고, 이런 포인터 변수를 지칭하는 용어는 dangling pointer 입니다.
그리고 이런 dangling pointer 를 역참조(dereference)하게 되면 segfault가 됩니다.
Signature :) - "여유를 갖고 행동하되 게을러지지 말자"
자바 프로그래머신가요? 질문 수준에 비해서 코딩이
자바 프로그래머신가요? 질문 수준에 비해서 코딩이 깔끔한걸로 봐서는 다른거하시다가 C를 공부하시나 봅니다.
포인터는 객체 그 자체가 아니라 어떤 정수값일 뿐입니다. 그 정수값이 메모리의 어떤 번지수에 대응된다는게 일반적인 정수와 다른 점입니다.
'객체 o를 가리키는 포인터 p'라고 자주 표현을 하지만, 그렇다고 정말로 그 포인터가 곧 그 객체를 나타내는게 아닙니다.
포인터는 어떤 주소값을 담고 있을 뿐이고, '객체 o를 가리키는 포인터 p'라는 표현은 단순히 포인터 p의 값과 객체 o의 주소값이 일치한다는 것의 관용적인 표현입니다. 포인터 p1과 p2가 모두 같은 객체 o를 가리키고 있다고 해도, p1의 값을 바꾼다고 p2의 값이 바뀌지는 않습니다. p1과 p2는 그냥 서로다른 정수 변수일 뿐이니까요.
이는 함수 인자에 대해서도 마찬가지입니다. C의 모든 함수 인자는 call-by-value로 넘어가기 때문에, Data_a_Release(Data_a *pSecureData) 에서 pSecureData는 함수로 넘긴 변수(이경우에는 main함수내의 data_a)와 값이 같은 또 다른 변수입니다. 따라서 pSecureData의 값이 바뀐다고 해서 전혀 다른 변수인 data_a의 값이 바뀌지 않습니다. 자바에서도 primitive-type은 call-by-value라고 알고 있는데, 포인터를 넘기고 그 안에서 포인터에 대입하는 건, 그냥 정수하나 넘기고 그안에서 대입하는 것과 동작원리가 동일합니다.
감사합니다
이해가 잘 되었어요. 그런데, 그럼 Release함수에서 free를 하더라도 메모리 헤재가 되지 않나요?
그러면 free해주고 싶을 땐 어떻게 해야 하나요
메모리는 해제됩니다. 메모리를 해제하는 것과,
메모리는 해제됩니다. 메모리를 해제하는 것과, 포인터의 값을 바꾸는 건 별개입니다. 다시 강조하지만 포인터는 그냥 어떤 주소값을 담고 있는 정수 변수일 뿐입니다. free의 인자로 포인터를 넘기는 것은 포인터를 해제하라는 뜻이 아니라 이 포인터의 값에 해당하는 주소에 할당된 메모리를 해제하라는 겁니다. 포인터 변수자체는 그냥 주소값이니까 그 주소에 어떤 객체가 할당되어있던 안되어있던 아무상관이 없습니다.
함수안에서 함수로 넘긴 변수의 값을 바꾸고 싶을 때 사용하는게 포인터인데, 함수안에서 포인터가 가리키는 메모리를 해제한 후에 이 포인터의 값이 NULL로 바뀌도록 하고 싶으신거라면 포인터의 포인터(이중 포인터)를 사용해야 합니다. 함수를 호출할때에는 포인터가 아니라 포인터의 주소값을 넘겨줘야하고요.
감사합니다.
slice_sd는 Data_b* 형태이고, 사용하다가 헤재하려 합니다.
printf("slice_sd = %p, slice_sd->pData = %p\n", slice_sd, slice_sd->pData);
sres = Data_a_Release(slice_sd);
printf("slice_sd = %p, slice_sd->pData = %p\n", slice_sd, slice_sd->pData);
slice_sd->size = 3;
printf("slice_sd->size = %d\n", slice_sd->size);
이렇게 테스트를 해봤습니다.
slice_sd = 0x98dca78, slice_sd->pData = 0x98dca90
slice_sd = 0x98dca78, slice_sd->pData = (nil)
slice_sd->size = 3
결과는 이렇구요.
왜 slice_sd는 값이 (nil)이 아닌가요?
만약, slice_sd가 해제 되었다면 slice_sd->size는 값이 들어가면 안될텐데요
free한다고 자동으로 포인터가 NULL로 바뀌지
free한다고 자동으로 포인터가 NULL로 바뀌지 않습니다. 그 이유는 앞에서 전부 설명했습니다.
댓글 달기