C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[55259] Re:Re:Re:Re:AnsiString 와 char * 비교 부탁드립니다.
아제나 [azena] 1819 읽음    2008-11-24 18:03
멋진 글 잘 보았습니다. ^^
역시 볼포에는 고수님이 너무 많이 계시네요 ㅎㅎ

리턴값의 c_str()의 사용은 정말 위험한 것이였네요.
자동 변수 배열의 리턴과 같은 결과를 낳는군요.


장성호 님이 쓰신 글 :
: TEdit의 Text는 AnsiString 변수가 아니라
: Property입니다.
:
: 계속 VCL코드를 따라 올라가도 실제 String형 변수가 존재하지 않습니다.
:
: TEdit의 경우 실제 내용을 만들어서 반환해주는 부분이
:
: TControl의  GetText 메소드입니다.
: TCaption은 String형입니다.
:
:
: function TControl.GetText: TCaption;
: var
:   Len: Integer;
: begin
:   Len := GetTextLen;
:   SetString(Result, PChar(nil), Len);
:   if Len <> 0 then GetTextBuf(Pointer(Result), Len + 1);
: end;
: 
: function TControl.GetTextBuf(Buffer: PChar; BufSize: Integer): Integer;
: begin
:   Result := Perform(WM_GETTEXT, BufSize, Longint(Buffer));
: end;
: 
: function TControl.GetTextLen: Integer;
: begin
:   Result := Perform(WM_GETTEXTLENGTH, 0, 0);
: end;
: 
: 

:
: GetText 함수에보면 에서 SetString으로 메모리를 확보하고 난뒤에
: GetTextBuf 를 호출하는데  GetTextBuf메소드를 보면
: WM_GETTEXT를 메세지를 control에 보내 버퍼에 내용을 닮습니다.
:
: 즉 Edit의 Text에 접근할때마다 새로 메모리를 할당해서 WM_GETTEXT로 가져오는것입니다.
:
: 그렇다면 저 SetString으로 확보된 메모리는 언제 해제되는것인가?
:
: 그것은 GetText 메소드가 return된뒤에 곧바로 해제됩니다.
: 왜 곧바로 해제되는가 하면?
:
: 아제나님의 말씀대로 AnsiString을 Reference Count 를 하고 있습니디다.
:
: 그런데 AnsiString으로 Edit의 text를 받았으면
: Reference Count 가 증가해서 해제가 되지 않을것인데..
:
: chat *를 받았기 때문에 Reference Count가 증가하지 않아서 해제되는것입니다.
:
:
: 만약 님께서  다음과 같이 해보십시요
:
:
: void __fastcall TForm1::Button1Click(TObject *Sender)
: {
:     char *Data = vEditInterval->Text.c_str();
: 
:      int length = StrLen(vEditInterval->Text.c_str());
: 
:      String s="abcd를 넣으면? Data에 abcd가 들어갑니다.";
:      for(int i= 0; i=Data[i])&&(Data[i]<='9')))
:          {
:              MessageDlg("숫자만 입력하세요", mtWarning, TMsgDlgButtons() << mbOK, 0);
:              return;
:          }
:      }
: }
: 

:
:  vEditInterval->Text.c_str(); 호출이후에
: String변수를 하나 생성해서 데이타를 넣어보십시요
:
: 그러면 Data의 내용이 String s의 내용과 같게 될것입니다.
:
: 만약  String으로 Edit의 Text를 받게되면
: String s=vEditInterval->Text;
: 똑같이 TControl의 GetText가 호출되지만 return된후에 memory해제는 되지 않게 됩니다.
:
:
: String의 Reference Count를 체크해보고 메모리 해제를 하는함수가
: System유닛에 _LStrClr 함수이더군요
: vEditInterval->Text.c_str(); 또는 vEditInterval->Text 접근하고 맨마지막에
: 항상 _LStrClr 함수가 호출되는데
: String변수고 받은경우에는 LStrClr 함수에서 FreeMem이  호출되지 않더구요
:
:
: procedure _LStrClr(var S);
: asm
:         { ->    EAX pointer to str      }
: 
:         MOV     EDX,[EAX]                       { fetch str                     }
:         TEST    EDX,EDX                         { if nil, nothing to do         }
:         JE      @@done
:         MOV     dword ptr [EAX],0               { clear str                     }
:         MOV     ECX,[EDX-skew].StrRec.refCnt    { fetch refCnt                  }
:         DEC     ECX                             { if < 0: literal str           }
:         JL      @@done
:    LOCK DEC     [EDX-skew].StrRec.refCnt        { threadsafe dec refCount       }
:         JNE     @@done
:         PUSH    EAX
:         LEA     EAX,[EDX-skew].StrRec.refCnt    { if refCnt now zero, deallocate}
:         CALL    _FreeMem            //String변수로 받은경우 FreeMem이 호출안됨
:         POP     EAX
: @@done:
: end;
: 

:
:
: 다음그림은 아래코드를 실행할때 CPU디버깅 창의 내용입니다.
: 참고하세요
: //코드1
: void __fastcall TForm1::Button3Click(TObject *Sender)
: {
:     String s;
:     s=vEditInterval->Text;
:     ShowMessage(s);
: }
:
:
:
: //코드2
: void __fastcall TForm1::Button1Click(TObject *Sender)
: {
:     char *Data = vEditInterval->Text.c_str();
:
:     ....
: }
:
:  
:
:
: 앗참 "민간돼지"님
: 숫자만을 받기 위한 for구문내의 비교구분에 문제가 있네요
: 이글에 약간 수정했습니다. 참고하세요
:
: 그럼..
:
:
: 아제나 님이 쓰신 글 :
: : AnsiString 내부적으로 Reference Count를 구현하고 있기 때문에
: : 리턴값에 사본을 쓰지 않는 것으로 알고 있습니다.
: :
: : c_str() 값은 AnsiString의 값이 수정되기 전까지 내용이 유지되는데
: : 변경될리도 없을 것 같은데요... 흠....
: :
: : BCB 버젼별 AnsiString 구현 방법에 차이가 있는 것인지.... 어렵군요... ^^
: :
: :
: :
: : 김태선 님이 쓰신 글 :
: : : vEditInterval->Text는 프로퍼티로서 여기서 데이타를 취하려하면
: : : 새로 배정된 메모리에 있는 사본에 대한 값을 줍니다.
: : : 그러므로
: : :
: : :      char *Data = vEditInterval->Text.c_str();
: : :
: : : Data에는 사본 데이타 번지가 받아 집니다.
: : :
: : :      int length = StrLen(vEditInterval->Text.c_str());
: : :
: : : 다시 프로퍼티를 제어하므로, 이때 Data가 가르키는 이전 사본은 폐기됩니다.
: : : 그러므로 Data[x] 를 제어하려고 하면 엉뚱한 데이타가 걸리는 것입니다.
: : : 물론 새로 메모리 할당/해제가 없는 경우는 사본을 폐기해도 그 내용까지 메모리에서
: : : 지우진 않기 때문에 마치 진짜처럼 읽을 가능성도 있지만, 이는 버그 프로그램 만드는 좋은 방법일 뿐입니다.
: : :
: : : 스트링 클래스와 프로퍼티 특성상 그렇게 처리할 수 밖에 없으니
: : : 프로퍼티에서 직접 String 번지를 받는 방법은 절대 사용하면 안됩니다.
: : : 위처럼 사용하기도 전에 폐기 됩니다.
: : :
: : :
: : : 민간돼지 님이 쓰신 글 :
: : : : 아래와 같이 실행하면 Data값이 제대로 나오는데요
: : : : //////////////////////////////////////////////////////////////////
: : : :     AnsiString TESTData;
: : : :     TESTData = vEditInterval->Text;
: : : :     char *Data = TESTData.c_str();
: : : :
: : : :     int length = StrLen(vEditInterval->Text.c_str());
: : : :
: : : :     for(int i= 0; i<length; i++)
: : : :     {                                                                                                                    -
: : : :         if(!('0'<=Data[i]&&Data[i]<='9'))
: : : :         {
: : : :             MessageDlg("숫자만 입력하세요", mtWarning, TMsgDlgButtons() << mbOK, 0);
: : : :             return;
: : : :         }
: : : :     }
: : : : //////////////////////////////////////////////////////////////////
: : : : 아래와 같이 실행하면 Data값이 이상하게 나오는데 차이를 모르겠습니다.
: : : : /////////////////////////////////////////////////////////////////
: : : :
: : : :     char *Data = vEditInterval->Text.c_str();
: : : :
: : : :     int length = StrLen(vEditInterval->Text.c_str());
: : : :
: : : :     for(int i= 0; i<length; i++)
: : : :     {                                                                                                                    -
: : : :         if(!('0'<=Data[i]&&Data[i]<='9'))
: : : :         {
: : : :             MessageDlg("숫자만 입력하세요", mtWarning, TMsgDlgButtons() << mbOK, 0);
: : : :             return;
: : : :         }
: : : :     }
: : : : /////////////////////////////////////////////////////////////////////////////////////////////////////
: : : :     AnsiString TESTData;                                   //
: : : :     TESTData = vEditInterval->Text;                    //                char *Data = vEditInterval->Text.c_str();
: : : :     char *Data = TESTData.c_str();                    //
: : : : ////////////////////////////////////////////////////////////////////////////////////////////////////
: : : : 초보적인 질문이지만 비교  부탁드리겠습니다.  너무 궁금해서요

+ -

관련 글 리스트
55222 AnsiString 와 char * 비교 부탁드립니다. 민간돼지 1885 2008/11/21
55242     Re:AnsiString 와 char * 비교 부탁드립니다. 김태선 1604 2008/11/24
55250         Re:Re:AnsiString 와 char * 비교 부탁드립니다. 아제나 1551 2008/11/24
55253             Re:Re:Re:AnsiString 와 char * 비교 부탁드립니다. 장성호 1606 2008/11/24
55259                 Re:Re:Re:Re:AnsiString 와 char * 비교 부탁드립니다. 아제나 1819 2008/11/24
55247         Re:Re:AnsiString 와 char * 비교 부탁드립니다. 민간돼지 1261 2008/11/24
55233     Re:AnsiString 와 char * 비교 부탁드립니다. 아제나 1625 2008/11/21
55248         Re:Re:AnsiString 와 char * 비교 부탁드립니다. 민간돼지 1340 2008/11/24
55227     Re:AnsiString 와 char * 비교 부탁드립니다. 장성호 2195 2008/11/21
55228         Re:Re:답변 감사드립니다. 민간돼지 1367 2008/11/21
55223     저는 잘 되는데요. 근데 '-' 이건 뭐에요? 조대현.Clau 1435 2008/11/21
55226         Re:저는 잘 되는데요. 근데 '-' 이건 뭐에요? 민간돼지 1395 2008/11/21
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.