2016-05-19 27 views
0

Ich habe eine Klasse wie folgt:Zugriffsverletzung in einer delphi Klasse

Component = class(TObject) 
    Name: string;    
    CurState: word;    
    States: array of state; 
    constructor Create(nm: string); 
    procedure AddState(ccl: bool; const InB: BufArr; const OutB: BufArr); 
    function GetStateCount(): Integer; 
    end; 

States ist ein Array von state, die auch eine Klassendeklaration ist.

State = class(TObject)  
    InBuf: BufArr;    
    OutBuf: BufArr;   
    Cycle: bool;  
    constructor Create(ccl: bool; const InB: BufArr; const OutB: BufArr); 
    end; 

kann Jeder component halten mehr als ein state, weshalb ich eine Reihe von state haben.

Die GetStateCount() Funktion sollte die Anzahl der Zustände eine Komponente has.The Implementierung Rückkehr ist wie folgt:

function Component.GetStateCount(): Integer; 
begin 
    result:=Length(States); 
end; 

Allerdings, wenn ich diese Funktion in einem anderen Verfahren nennen, ich die folgende Fehlermeldung erhalten:

enter image description here

Ich kann nicht scheinen, die Ursache dafür herauszufinden. Ich werde jede Hilfe zu schätzen wissen.

Okay, hier ist der Teil des Codes, wo ich die Funktion bin Aufruf:

for i:=0 to nc-1 do 
begin 
cycle:=false; 
len:=cmp[i].GetStateCount; 
for j:=0 to len-1 do 
    if not cmp[i].States[j].Cycle or cycle then 
    continue; 
    cycle:=true; 
    for k:= 0 to length(cmp[i].States[j].InBuf)-1 do 
    begin 
    m:=cmp[i].States[j].InBuf[k]; 
    if m>0 then 
    graph[m-1,i]:= graph[m-1,i]+1; 
    end; 
    end; 
+0

Können Sie voll * .pas Code? –

+0

Das ist nicht dein richtiger Code. Wenn Sie Hilfe bei einem Problem mit Ihrem Code benötigen, geben Sie Ihren tatsächlichen Code ein. Es zu machen, wenn du gehst, ist nutzlos; Es kann neue Probleme verursachen oder das eigentliche Problem verbergen. Was Sie gepostet haben, ist in keiner Weise vollständig, und es kann nicht zum Testen kompiliert und/oder verwendet werden. Lies [mcve] und [edit] deine Frage, wenn du uns helfen willst. –

+0

@KenWhite das ist in der Tat nicht sein komplettes Projekt. Aber Sie haben keinen Grund zu sagen, dass der Code "nicht echt" ist, ist es höchstwahrscheinlich. –

Antwort

1

Read of address 0000000xx - beachten Sie die referenzierte Adresse nahezu Null ist, aber leicht darüber - legt nahe, dass Sie nicht Objekt erstellt haben wenn Sie versuchen, auf seine internen Felder zuzugreifen (innerhalb des Aufrufs dieser Funktion).

dass Hypothese Ihre Funktion umschreiben Um zu testen, dass „defensive Programmierung“ Art und Weise:

function Component.GetStateCount(): Integer; 
begin 
    if nil = Self then 
    raise Exception.Create ('I forgot to create the object!'); 

    result := Length(Self.States); 
end; 

Wenn die angepasste Ausnahme ausgelöst wird - es dann ist, und Sie sollten debuggen, warum Sie die Komponente nicht erstellt haben.

Feldvariablen Ihrer Komponentenobjekte werden vom Wert Self Zeiger versetzt. Und für Win32-Programme würden sie typischerweise memory-aligned bis 4-Byte (32 Bit) Grenzen sein.

So würden wir

  • Selbst + 0 ==> Zeiger auf die VMT (Virtual Methoden Tabelle)
  • Selbst + 4 ==>Component.Name // Zeiger auf TStringRec
  • Selbst haben + 8 ==>Component.CurState // zwei Bytes verwendet, zwei Bytes "gepolsterte"
  • Selbst + 12 ==>Component.States // Zeiger auf dyn-Array-Rahmen

hexadezimal 0000000C ist genau 12, was (0 + 12) ist, wenn (Self=nil).

Internal Data Formats (Delphi)

Hinweis: in Delphi 7 einige Formate unterschiedlich waren, zum Beispiel lange Strings nicht das Codepage-Feld haben.


Im Code auf die Frage cmp[i] manchmal ist nil - und Sie müßten, um zu bestimmen, ob die gültige Situation ist oder nicht.

Wenn es gültig ist, müssen Sie innerhalb der Schleife darauf achten.

for i:=0 to nc-1 do 
begin 
    if nil = cmp[I] then continue; 
    cycle:=false; 
    ... 

Wenn es sollten Sie ermitteln, müßten keine nil Elemente im Array sein, wie das passieren konnte.

Aber ich glaube, das ist der Punkt einer separaten Forschung (und vielleicht Frage). Hier haben Sie gefragt, warum AV in der spezifischen Funktion war und ich denke, dass Sie die Self is nil Hypothese als die direkte Ursache überprüfen müssen.

Auch - die wiederholte Verwendung von cmp[i] im Ringkörper sieht nicht gut für mich. Ich empfehle Ihnen, den Wert in eine lokale Variable zwischenzuspeichern, die Sie genau dafür erstellen würden.

for i:=0 to nc-1 do 
begin 
    curr_cmp := cmp[i]; 
    if nil = curr_cmp then raise Exception.Create(....); 
    cycle := false; 
    len := curr_cmp.GetStateCount; 
    for j:=0 to len-1 do 
    if not curr_cmp.States[j].Cycle or cycle then 
     ... 

Es würde Brief machen Bearbeitung und Verständnis des Codes einfacher. Wenn Sie morgen diesen Code in eine separate Prozedur verschieben würden oder das Objekt von einer anderen Quelle als cmp[i] erhalten würden, müssten Sie nur EINE einzelne Zeile ändern, anstatt nach den cmp[i] Ereignissen zu suchen, bei denen ein oder zwei verloren gehen. Ich erinnere mich, einmal musste ich die Indexvariable von der einfachen Schleife zu einem viel komplexeren indirekten Muster ändern, eigentlich musste ich anfangen, zwei Indexvariablen zu verwenden, und dann lazy copy-pasting cmp[i] Bit mich ziemlich ekelhaft ...

Und vielleicht würde das den Code auch etwas schneller machen.

+0

Der Versuch, diese Frage ohne eigentlichen Code im OP zu beantworten, ist weder für diesen Benutzer noch für zukünftige Leser von Vorteil, und es beseitigt den Anreiz für das OP, die Frage zu bearbeiten, um den eigentlichen Code bereitzustellen. –

+0

'ohne jeden tatsächlichen Code in der OP' - ist wahrscheinlich Täuschung und Wunschdenken. Es gibt keinen Grund dafür, dass der Code nicht real ist. –

+0

Der Code wird nicht kompiliert, es gibt keine Informationen über den Konstruktor und es gibt typografische Fehler. Es ist kein echter Code und es ist sicherlich kein MCVE. –

5

Ihr States Mitglied ist $00000000C innerhalb der Klasse Component versetzt, so dass ein Read of address 0000000C Fehler bedeutet das States Element aus einem nil Component Zeiger zugegriffen wird. $00455F54 ist die Speicheradresse des Codes, der GetStateCount() aufruft. Verwenden Sie den Debugger, um zu dieser Speicheradresse zu springen (wenn er Sie dort beim Auftreten des Fehlers nicht schon automatisch hingeführt hat) und herauszufinden, warum dieser Code auf einen Null-Zeiger zugreift.


aktualisieren: Basierend auf den Code-Snippet Sie hinzugefügt haben, das Problem durch cmp[i] ist null verursacht wird. Sehen Sie sich den Code an, der cmp zuweist und füllt, da er nicht korrekt ausgefüllt wird. Meine Vermutung ist, dass Sie wahrscheinlich cmp selbst sind Zuteilen aber keine Component Objektzeiger in sie kopieren zu vergessen, zum Beispiel:

for I := 0 to nc-1 do 
    cmp[i] := Component.Create; // <-- HERE! 
+0

Warum der Downvote? –

+0

Siehe Kens Kommentare zu meiner Antwort. Bis der Topicstarter ihm die TOTAL-Quellen zu seinem Projekt geben würde, möchte er nicht, dass diese Frage beantwortet wird. –

+3

@ Arioch'The: Das garantiert keinen Downvote auf eine legale Antwort. Und es ist nicht Ken's Entscheidung, ob Antworten gepostet werden können oder nicht. Wenn Ken möchte, dass die Leute diese Frage ignorieren, kann er eine enge Abstimmung abgeben (was anscheinend noch niemand getan hat). Es ist ziemlich einfach, aus den OP-Informationen herauszufinden, was passiert ist (auf einen Nullzeiger wird zugegriffen). Wenn das OP herausfinden will, warum auf einen Null-Zeiger zugegriffen wird, kann das OP diese Frage aktualisieren, um den aufrufenden Code anzuzeigen oder eine neue Frage zu posten. –