2015-02-05 5 views
2

델파이에 익숙하지 않아 배열 "nieuwButtons"에 액세스하려고 할 때 액세스 위반이 계속 발생합니다. 누구든지 내가 뭘 잘못하고 있는지 알 수 있니? TGeneral 인스턴스가 유효하지 않은 경우배열에 액세스하려고 할 때 액세스 위반이 계속 발생합니다.

unit UGeneral; 

    interface 

    uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, 
    System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Grids, Vcl.DBGrids, SMDBGrid, 
    KJSMDBGrid, Vcl.ExtCtrls, KJPanel, Vcl.StdCtrls, Vcl.Mask, Vcl.DBCtrls, 
    Data.DB; 

    type 
    TGeneral = class(TObject) 

    private 
     { Private declarations } 

    public 
     nieuwButtons: array of TButton; 
     nieuwButtonsDataSource: array of TDataSource; 

     procedure listEdits(x, y: Integer; owner: TComponent; parent: TWinControl; 
     source: TDataSource); 
     procedure nieuwClick(Sender: TObject); 
     { Public declarations } 
    end; 

    var 
    General: TGeneral; 

    implementation 

    procedure TGeneral.nieuwClick(Sender: TObject); 
    var 
    i: Integer; 

    begin 
    for i := 0 to Length(nieuwButtons) - 1 do 
    begin 
     if (nieuwButtons[i] = Sender) then 
     begin 
     nieuwButtonsDataSource[i].DataSet.Insert; 
     end; 
    end; 
    end; 

    procedure TGeneral.listEdits(x, y: Integer; owner: TComponent; 
    parent: TWinControl; source: TDataSource); 
    var 
    i: Integer; 
    edit: TDBEdit; 
    _label: TLabel; 
    biggestWidth: Integer; 
    button: TButton; 
    edits: array of TDBEdit; 
    index: Integer; 
    begin 
    if nieuwButtons <> nil then //I get an access violation here 
    begin 
     SetLength(General.nieuwButtons, 0); 
     SetLength(nieuwButtonsDataSource, 0); 
    end; 
    index := Length(nieuwButtons); 
    SetLength(nieuwButtons, index + 1); 
    SetLength(nieuwButtonsDataSource, index + 1); 
    button := TButton.Create(owner); 
    button.parent := parent; 
    button.Top := y; 
    button.Left := x; 
    button.Caption := 'Nieuw'; 
    button.OnClick := nieuwClick; 

    nieuwButtons[index] := button; 
    nieuwButtonsDataSource[index] := source; 

    biggestWidth := 0; 
    SetLength(edits, source.DataSet.Fields.Count); 
    edit := TDBEdit.Create(owner); 
    for i := 0 to source.DataSet.Fields.Count - 1 do 
    begin 
     _label := TLabel.Create(owner); 
     _label.parent := parent; 
     _label.Caption := source.DataSet.Fields[i].FieldName; 
     _label.Top := ((i * 22) + 30 + y); // 22 = standaard(?) hoogte van edittext 
     _label.Left := x; 

     _label.Show; 

     if _label.Width > biggestWidth then 
     begin 
     biggestWidth := _label.Width; 
     end; 
    end; 
    i := 0; 
    for i := 0 to source.DataSet.Fields.Count - 1 do 
    begin 
     edit := TDBEdit.Create(owner); 
     edit.parent := parent; 
     edit.DataField := source.DataSet.Fields[i].FieldName; 
     edit.DataSource := source; 
     edit.Top := ((i * edit.Height) + 30 + y); 
     edit.Left := biggestWidth + 30; 
     edits[i] := edit; 
     edit.Show; 
    end; 

    end; 

end. 
+0

액세스 위반이 너무 던졌습니다 :/ – user2073973

+0

이 위치는 제안 'Self'는'nil'입니다. 'listEdits'를 호출하는 방법을 보여줍니다. –

+0

General.listEdits (0, 0, Self, KJPanel4, DataModule2.bestemmingSource); – user2073973

답변

5

예외를 발생하는 코드 줄 수있는 유일한 방법이다.

오류는 클래스를 인스턴스화하는 코드에서 찾을 수 있습니다. 이 오류의 일반적인 형태는 다음과 같습니다.

  1. 개체를 전혀 인스턴스화하는 것을 잊어 버립니다.
  2. 형식이 아닌 초기화되지 않은 인스턴스에서 생성자를 호출하여 개체를 잘못 인스턴스화합니다.

    var 
        General: TGeneral; 
    .... 
    General.Create; // sometimes this way 
    General := General.Create; // or sometimes this way 
    

    을하지만 올바른 방법은 다음과 같이이다 :

은 후자의 오류를 설명하기 위해, 그것은 다음과 같습니다 할당

General := TGeneral.Create; 
+0

감사합니다! 이것으로 해결되었습니다. 개체가 아직 인스턴스화되지 않았을 때 일반 내부의 함수를 호출 할 수있는 방법이 이상하다고 생각합니다. – user2073973

+1

여기'General'은 실제로 포인터 이상입니다. 'General.DoSomething (42)'을 쓸 때 실제로 일어나는 것은 메서드 호출의 제목이 추가 암시 적 매개 변수로 전달된다는 것입니다. 정말 TGeneral.DoSomething (General, 42)입니다. 이제'General'이 유효한 인스턴스를 가리 키도록 초기화되지 않았다면 호출은 괜찮지 만'Self '를 참조하려고 할 때 객체 내부에서 일반적으로 런타임 오류가 발생합니다. –

+0

아, 그건 이해가 돼요! 델파이에서 지금까지 2 일 동안 프로그래밍 만 해왔다는 것을 몰랐습니다. 몇 분 안에 해결책으로 답을 표시하겠습니다. – user2073973