요거는 저도 정확히 모르는 어려운 문제네요
빌더의 VCL에 델파이(Object-pascal)로 만들어져 있는것 이시죠?
델파이 컴파일러에서는 String이 int 나 word 처럼 컴파일 기본형입니다.
그런데 C++빌더에선느 String이 컴파일기본형이 아니라 AnsiString이라는 클래스로 구현되어있습니다.
델파이의 String과 빌더의 AisiString클래스와 어떻게 맞추었는지 참 신기한데....
여튼 그사에에서 나는 문제 같습니다.
보통
Delphi의 string에서 c++빌더의 AnsiString으로 받는것은 문제없던데
Edit의 Text변수는 AisiString형이기는 하지만 그냥 변수가 아니라 property입니다.
즉 Edit->Text를 접근하면 그때 VCL의 Controls유닛에 있는 GetText라는 함수가 호출되고
거 함수안에서 버퍼를 확보하고 test의 내용을 복사합니다.
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;
위 GeText함수에서 TCaption은 String형입니다.
GetText함수를 통해 String형은 넘겨 받는데
이때 C++의 AnsiString클래스에서 받습니다.
c++ AisiString클래스의 대입연산자 가 동작하고
c_str() 로 포인터에 접근할때 AisiString클래스의 c_str() 함수가 호출될것입니다.
위 두과정에서 무엇인가 꼬이는것 같습니다.
정확한 원인은 고수님들께.....
dstirng.h 파일에 C++빌더 AnsiString클래스가 정의되어있습니다.
아래와 같이 여러가지의 생성자가 있는데...
__fastcall AnsiString(): Data(0) {} //첫번째
__fastcall AnsiString(const char* src); //두번째
__fastcall AnsiString(const AnsiString& src);//세번째..
....
등등..
위의 경우 세번째 생성자가 호출되지 않을까 생각했는데...
실제로는 첫번째 생성자가 호출되더군요
그리구..
그렇다면 대입연산자 같은게 호출되어야 하는데 호출되지 않는것 같구
AnsiString& __fastcall operator =(const AnsiString& rhs);
언제 실제copy가 일어나느지 잘 모르겠더군요
그런후에 곧바로
char* __fastcall c_str() const { return (Data)? Data: "";}
가 호출되더군요...
//-----------------------------------------------------------
하여튼 Control에 Text나 Caption은 실제 String변수가 아니라
property로 구현되어있다는것을 기억할 필요가 있구요
호출될때마다 새로 String을 만들어서 복사한후에 return한다는것도 기억하구요
가능하면 AnsiString변수에 대입한후에 string변수를 사용하는것이 좋을듯 합니다.
그리고 StrLen 보다는
AnsiString에 있는 Length라는 함수를 쓰는것이 훨씬 빠릅니다.
왜냐하면 AisiString은 Data라는 포인터 변수 한개만 가지고 있습니다만
실제 Data가 가리키는 곳에 가면
Data 앞쪽에 StrRect 이라는 12Byte가 더 생성되어있습니다.
struct StrRec {
int allocSiz;
int refCnt;
int length;
};
StrLen으로 Length를 계산하면 0x00이 나올때까지 찾아서 length를 return하지만
String의 Length를 함수를 사용하면
저 StrRec에서 length를 바로 return해줍니다.
SetLength로 256Byte를 잡아놓고 0x00으로 모두 채워놓은경우
StrLen으로 체크하면 size가 0이지만 AisiString클래스의 Length함수를 사용하면
256이 곧바로 튀어나오게 되죠
정확한 답은 못드렸는데...
도움이 될까하여
그냥 C++빌더의 AisiString에 대해 두서없이 서술합니다.
그럼...
민간돼지 님이 쓰신 글 :
: 아래와 같이 실행하면 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(); //
: ////////////////////////////////////////////////////////////////////////////////////////////////////
: 초보적인 질문이지만 비교 부탁드리겠습니다. 너무 궁금해서요