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
[52474] Re:에러 원인좀 찾아 주세요..
[] 1148 읽음    2008-02-29 12:53
구윤태 님이 쓰신 글 :
: 1.
: 프로젝트에  TCD_DataStruct.h  파일생성후
:
: [TCD_DataStruct.h]
:
: #ifndef __TCD_DataStructH__
: #define __TCD_DataStructH__
:
:  typedef struct
: {
:    AnsiString  PatientsID;
:    AnsiString  ChartNo;
:    AnsiString  Name;
:    TDateTime   Birth;
:    AnsiString  Sex;
:    AnsiString  Telephone;
:    AnsiString  Address;
:    AnsiString  Remark;
:    TDateTime   RegistDate;
: } PATIENT;
:
: #endif
: ============================================================================
: 2.  프로젝트 공유 클래스 생성 TCD_ShareData.h
: [TCD_ShareData.h]
: #ifndef TCD_ShareDataH
: #define TCD_ShareDataH
: #include "TCD_DataStruct.h"
:
: class TCD_ShareData
: {
:  private:
:         PATIENT pPatient;
:  public:
:         TCD_ShareData();
:         ~TCD_ShareData();
:         void __fastcall SetPatient(PATIENT mPatient);
:         PATIENT __fastcall GetPatient();
: };
: extern PACKAGE TCD_ShareData *tcdSD;
: #endif
:
:
: [TCD_ShareData.cpp]
: #pragma hdrstop
: #include <vcl.h>
: #include "TCD_ShareData.h"
: #include "Trace.h"
:
: TCD_ShareData *tcdSD;
: TCD_ShareData::TCD_ShareData()
: {
: }
: TCD_ShareData::~TCD_ShareData()
: {
: }
: void __fastcall TCD_ShareData::SetPatient(PATIENT mPatient)
: {
:   pPatient = mPatient;
: }
: PATIENT __fastcall TCD_ShareData::GetPatient()
: {
:   return pPatient;
: }
: #pragma package(smart_init)
: ===========================================================================================
:
: 3. Form 생성
:
:
: #ifndef TCD_PatientInputH
: #define TCD_PatientInputH
:
: #include <Classes.hpp>
: #include <Controls.hpp>
: #include <StdCtrls.hpp>
: #include <Forms.hpp>
: #include <ExtCtrls.hpp>
: #include <jpeg.hpp>
: #include <Mask.hpp>
: #include <ComCtrls.hpp>
:
:
: class Tpatientinput : public TForm
: {
: __published:    // IDE-managed Components
:     TImage *Image1;
:     TImage *okImage;
:     TImage *cancelImage;
:         TMaskEdit *patientidEdit;
:
:     void __fastcall okImageClick(TObject *Sender);
:     void __fastcall cancelImageClick(TObject *Sender);
: public:        // User declarations
:     __fastcall Tpatientinput(TComponent* Owner);
:     //환자 데이터 구조체 저장
:     void __fastcall patientDataStore();
: };
: extern PACKAGE Tpatientinput *patientinput;
: //---------------------------------------------------------------------------
: #endif
:
:
:
: [TCD_PatientInput.cpp]
: //공유데이터
: #include <vcl.h>
: #pragma hdrstop
:
: #include "TCD_ShareData.h"
: #include "Trace.h"
:
: #pragma package(smart_init)
: #pragma resource "*.dfm"
:
: Tpatientinput *patientinput;
:
: //ok 버튼
: void __fastcall Tpatientinput::okImageClick(TObject *Sender)
: {
: //환자 정보 struct 저장
:   patientDataStore();
: }
:
: void __fastcall Tpatientinput::patientDataStore()
: {
:
:   //구조체에 환자 정보 저장하기
:   PATIENT mPatient;
:   mPatient.PatientsID= this->patientidEdit->Text;
:   TRACE("mPatient=%p  , mPatient.PatientsID=%s",mPatient,mPatient.PatientsID); //정상적으로 값이 표시 됩니다.
:   tcdSD->SetPatient(mPatient);
: }
:
:
:
:
: ---------------------------------------------------------------------------------------------
: 문의)
: 구조체 헤더정의후 , 공유 클래스를 생성해서 구조체 개체를 만들고
: 구초체를 받아서 처리하는 루틴 만든 다음
: 새로운 폼에서 공유클래스를 이용하여  PATIENT mPatient 생성한 곳에 , 객체를 전달 하여 주는 과정입니다.
:
:
: TCD_PatientInput.cpp 소스에서 ok버튼을 실행시키면
: 구조체의 값이 저장되어 SetPatient(mPatient)를 통해서
: TCD_ShareData.cpp 소스의 SetPatient함수를 실행시키는데
:
: void __fastcall TCD_ShareData::SetPatient(PATIENT mPatient)
: {
:   TRACE("mPatient=%p  , mPatient.PatientsID=%s",mPatient,mPatient.PatientsID); //정상적으로 값이 표시됩니다.
:   pPatient = mPatient; <-여기서 에러가 나타나는데 원인을 모르겠습니다.
: }
:
:
:
:
: 에러 내용
: Access violation at address 00432E0 in module 'TCD.exe' , Write of address 00000000
:
: 메세지가 나옵니다.

TCD_ShareData *tcdSD;  와 tcdSD->SetPatient(mPatient); 사이 어딘가에서,
TCD_ShareData 형의 인스턴스를 하나 생성해서 그 번지를 tcdSD 변수에 저장해주어야 됩니다.
tcdSD는 TCD_ShareData 인스턴스가 아니고 인스턴스의 번지를 저장/보관할 수 있는 포인터 변수입니다.
(32 비트 시스템에서 포인터 변수는 32 비트, 즉 4 바이트)
현재 tcdSD는 전역으로 선언/정의 되었으므로 기본값 0을 가지고 있는 상태입니다.

한편, 클래스 인스턴스 자체를 함수의 매개변수로 넘겨주면 인스턴스를 복사하는 데 불필요한 부하가 걸리므로 인스턴스의 번지 정보만을 넘겨 주는 게 좋습니다.
상황에 따라 아래 네 가지 형식 중 하나로 하는 게 좋습니다.
const PATIENT &
PATIENT &
const PATIENT *
PATIENT *

클래스 인스턴스 복사는, 달리 복사 생성자나 = 연산자를 구현해놓지 않는 한, 기본적으로 멤버 대 멤버로 이루어집니다.
클래스 인스턴스 복사에서 가장 문제 소지가 많은 곳은 멤버 변수 중 포인터 변수이고 기본형 변수들은 문제가 되지 않습니다. 클래스 인스턴스를 복사할 때는 두 인스턴스가 완전히 분리되거나 분리된 효과를 내는 기능이 있는 클래스여야야 복사 결과가 안전하다 할 수 있습니다.
위에서 pPatient = mPatient;에서  PATIENT 에는 AnsiString 형 멤버 변수들이 있는데 AnsiString에는 멤버 변수가 하나 있습니다. 그 변수는 문자열 버퍼를 가리키는 포인터 변수입니다. 다행히 AnsiString에는 Unique 메서드가 있어서 [] 연산자 호출시 자동으로 Unique 메서드가 호출되어 인스턴스 간에 동일한 문자열 버퍼를 사용하지 않도록 분리해줍니다. 내부 문자열 버퍼의 내용을 변경하거나 버퍼 자체를 바꾸는 다른 메서드들도 그러하리라 생각됩니다.
TDateTime에는 멤버 변수가 하나 있습니다. 그 변수는 double 형이므로 문제의 소지가 없습니다.

+ -

관련 글 리스트
52467 에러 원인좀 찾아 주세요.. 구윤태 1095 2008/02/28
52475     답변고맙습니다. 구윤태 940 2008/02/29
52474     Re:에러 원인좀 찾아 주세요.. 1148 2008/02/29
52473     Re:에러 원인좀 찾아 주세요.. 정성훈.해미 1088 2008/02/29
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.