String 클래스의 참조 카운트와 관련된 문제(?)로 보입니다.
대부분의 String 클래스는 참조 카운트(reference count)를 사용하는 걸로 알고있습니다.
String 객체는 실제 저장할 데이터를 가르키는 포인터를 가지고 있습니다. 그리고 대입 연산시 String객체는 새로운 데이터 공간을 할당하지 않고 기존의 복사할 데이터의 포인터 주소만 복사하고 참조 카운트를 하나 증가 시킵니다. 물론 이 참조 카운트는 동일한 데이터를 가르키는 객체들끼리 공유하게 되구요.
참조 카운트가 줄어드는 경우는 해당 데이터를 가르키는 객체가 소멸 되거나 그 데이터를 가르키던 String 객체에 다른
데이터가 복사 될때 입니다. 이 개념을 copy on write 라고 부르는데 지연 바인딩(?)의 일종으로 생각하시면 될 것 같습니다. 실제로 필요할때 까지 버팅기다가 최후에 메모리를 할당하자는 거죠.
결과적으로 참조카운트가 0이 될때 실제 data는 해제되게 됩니다.
만약 String객체를 사용해서 접근하신다면 참조카운트가 알아서 증가 감소 되기때문에 해제된 메모리에 접근할일은 거의 발생 안할 것으로 생각됩니다만..... 혹시 모르죠 또 그런 경우가 있을지도^^;
아마도 String클래스의 .data() 주소를 직접 참조하여 사용하신게 아닐까 감히 추측해 봅니다.
그리고 AsString의 주소가 계속 바뀌는 이유는 AsString()dl 임시객체를 생성하기 때문에 이전에 사용하신 AsString의 String 객체가 해제 되지 않았다면 다른 주소에 생성되는게 맞지 않을까 싶습니다. 만일 함수나 루프를 빠져나오면서 이전의 임시 객체가 해제되었다면 다시 그 주소를 사용할 것 같은데.... 이전에 사용하신 객체가 아직 어딘가에 사용되고 있나 봅니다. .data() 역시 마찬가지구요.
내공이 부족하여 말로 설명드리자니 한계가 있네요. 그리고 중요한거....이거 아닐 수도 있다는 거! ㅋ 틀린 부분이 있으면 다음분이 지적해 주시길 바라면서....이와 관련해서 이미 포럼에서 주옥 같은 글들이 많이 올라와 있었던 걸로 기억하고있습니다. 한번 찾아 보시길 추천 드립니다.
Starlet 님이 쓰신 글 :
: 조금 전에 원인을 알수 없는 문제로 씨름을 좀 했었습니다.
:
: 다음과 같은 함수가 있을 때...
:
:
: String Func(String Source, int Num)
: {
: String Ret;
:
: if (Num == 1)
: {
: Ret = Source;
: return Ret;
: }
: else
: { ............. }
: }
:
:
: 이 함수를
:
: Str = Func(SQLQuery->FieldByName("C_NAME")->AsString, 1);
:
: 이런식으로 사용할 수 있죠.
:
: 결론은 이렇게 쓰는 것이 위험하다는 것인데,
: 그 이유가 함수 내에서 Ret = Source 가 실핼될 때 Source가 가진 Data의 주소값이 그대로 Ret의 Data로 복사가 되고 Ret의 Data가 가진 주소값은 그 당시의 ->AsString의 Data 주소값과 같습니다. 그런데, ->AsString이 가진 Data값이 계속해서 변하더군요. 자주 메모리를 해제했다가 다시 다른 메모리에 할당했다가 그러더군요.
: 즉, Ret가 가진 Data의 주소가 이미 메모리에서 Free 되었다는 것입니다.
:
: 이럴 경우 Invalid pointer operation 오류가 나죠. 그런데 과연 이게 원인이 맞는지 모르겠네요. 그리고 왜 AsString의 문자열 주소가 계속 변할까요?