Seite 1 von 1

[kein Bug] Invalid Memory Access bei AddElement()

Verfasst: 27.02.2006 15:48
von NicTheQuick
Hi!

Bastel gerade an einem größeren Projekt und habe mir eine Laderoutine
gebastelt, die mehrere Elemente mit einer großen Struktur nacheinander
aus einer Datei einläd.

Um die Struktur einzulesen, benutze ich folgende allgemein gehaltene Routine:

Code: Alles auswählen

Procedure ReadStructure(FileID.l, *Var.AllTypes, *Struc.BYTE)
  Protected length.l
  
  While *Struc\b
    Select *Struc\b
      Case 'b' : *Var\b = ReadByte(FileID)      : *Var + 1
      Case 'c' : *Var\c = ReadCharacter(FileID) : *Var + 1
      Case 'w' : *Var\w = ReadWord(FileID)      : *Var + 2
      Case 'l' : *Var\l = ReadLong(FileID)      : *Var + 4
      Case 'f' : *Var\f = ReadFloat(FileID)     : *Var + 4
      Case 'd' : *Var\d = ReadDouble(FileID)    : *Var + 8
      Case 'q' : *Var\q = ReadQuad(FileID)      : *Var + 8
      Case 's'
        length = ReadLong(FileID)
        *Var\s = Space(length)
        ReadData(FileID, @*Var\s, length)
        *Var + 4
    EndSelect
    *Struc + 1
  Wend
EndProcedure
Das hier ist die Laderoutine:

Code: Alles auswählen

Procedure Sat_Load(File.s, Add.l = 0)
  Protected FileID.l
  If Add
    LastElement(Satellite())
  Else
    ClearList(Satellite())
  EndIf
  
  FileID = ReadFile(#PB_Any, File)
  If FileID
    a = ReadLong(FileID)
    While Eof(FileID) = 0 And a
      If AddElement(Satellite())
        ReadStructure(FileID, @Satellite(), @Struc_Satellite)
        a - 1
      EndIf
    Wend
    CloseFile(FileID)
  EndIf
EndProcedure
In der Zeile mit dem [c]AddElement(Satellite())[/c] kommt es nach
einigen Datensätzen, ca. 8 bis 10, zu einem Fehler und der Debugger
meldet "Invalid Memory Access". Kommentiere ich die nachfolgende Zeile
mit [c]ReadStructure(blabla)[/c] aus, funktioniert alles wunderbar, es
werden allerdings keine Daten in die Struktur eingelesen.

Bevor ich jetzt ein lauffähiges Beispiel poste, würde ich gerne wissen, ob
es mit [c]AddElement()[/c] schon ähnliche Probleme in der Beta gibt oder
nicht.

Danke!

Verfasst: 27.02.2006 15:54
von remi_meier
Auf den ersten Blick:
Wie sieht deine AllTypes-Struktur aus?
Deine erste Methode ist nicht allgemein, benutz da mal Unicode ;)

Verfasst: 27.02.2006 16:07
von NicTheQuick
Das ist meine Structure:

Code: Alles auswählen

Structure AllTypes
  StructureUnion
    b.b
    c.c
    w.w
    l.l
    f.f
    d.d
    q.q
    s.s
  EndStructureUnion
EndStructure
Allgemein galt eher für das Projekt. Da brauche ich kein Unicode.

Verfasst: 27.02.2006 16:12
von NicTheQuick
Die [c]ReadtStructure()[/c]-Funktion funktioniert übrigens tadellos. Wenn
ich ihr eine lokale Struktur übergebe und direkt mir Debug ein paar
Testwerte debugge, ist alles richtig.

Verfasst: 27.02.2006 16:18
von remi_meier
Ich frag jetzt mal nur zur Sicherheit, hast du die LinkedList auch wirklich
mit dieser Struktur deklariert?
Wenn ja, scheints langsam wirklich ein Bug zu sein :roll: oder ich steh
genauso aufm Schlauch wie du <)

Verfasst: 27.02.2006 16:40
von NicTheQuick
Hier mal der komplette Code: Code (Ziel speichern unter...)
So viel ist es nicht. Die Hauptdatei wäre [c]Inc_Satellite.pbi[/c]. Wenn
noch noch was fehlt, nochmal melden.

Verfasst: 27.02.2006 18:23
von remi_meier
Ganz einfach :) (Ne, musste lange suchen)
Entfern mal die StructureUnions aus deiner Struktur, also

Code: Alles auswählen

Structure Satellite
  Name.s            ; Satellitenname
  ;Teil 1
  Number.l          ; 03-07 Satellitennummer
  
  IntKennz_1.b      ; 10-11 Internationale Kennzeichnung (die beiden letzten Ziffern des Startjahres)
  IntKennz_2.w      ; 12-14 Internationale Kennzeichnung (Startnummer des Jahres)
  IntKennz_3.s      ; 15-17 Internationale Kennzeichnung (Stückbezeichnung)
  
  Epoche_y.c        ; 19-20 Epoche: Jahr (die beiden letzten Ziffern des Jahres)
  Epoche_d.d        ; 21-32 Epoche: Tag des Jahres mit Tagesbruchteil
  
  NDot.d            ; 34-43 Erste Zeitableitung der mittleren Bewegung (N-punkt) oder Ballistischer Koeffizient (je nach Ephemeriden-Typ)
  NDotDot.d         ; 45-42 Zweite Zeitableitung der mittleren Bewegung (N-punkt-punkt) (Dezimalpunkt wird unterstellt; leer falls unbekannt)
  
  ;StructureUnion  ; 54-61 BSTAR Reibungsterm bei GP4-Störungstheorie. Sonst Strahlungsdruck-Koeffizient.(Dez.punkt unterstellt)
    Reibungsterm.d 
    Strahlungsdruck.d
  ;EndStructureUnion
  
  Ephemeriden.c     ; 63-63 Ephemeriden-Typ
  
  Nummerierung.w    ; 65-68 Nummerierung der Two-Line-Elements
  
  ;Teil 2
  Inklination.d     ; 09-16 Inklination [Grad]
  Rektaszension.d   ; 18-25 Rektaszension aufsteigender Knoten (Knotenlage) [Grad]
  Exzentrizitaet.d  ; 27-33 Exzentrizität (Dezimalpunkt wird unterstellt)
  Perigaeumslage.d  ; 35-42 Perigäumslage [Grad]
  MidAnomalie.d     ; 44-51 Mittlere Anomalie [Grad]
  MidBewegung.d     ; 53-63 "Mittlere Bewegung" [Umläufe/Tag]
  AktUmlauf.l       ; 64-68 Nummer des aktuellen Umlaufs zur Epoche [Umläufe]
EndStructure
Dann läufts :)

Verfasst: 27.02.2006 21:25
von NicTheQuick
Ja, hab den Fehler mittlerweile schon selbst gefunden.
Die [c]StructureUnion[/c]s waren allerdings richtig. Falsch war folgende
Zeile. Da war ein "d" zuviel. So ist es richtig:

Code: Alles auswählen

Global Struc_Satellite.s = "slbwscddddcwddddddl"
Aber trotzdem Danke. Also kein Bug. Ich änder das mal im Titel.

Aber blöd ist trotzdem die Angabe des Fehlers. Anfangs hat er
[c]AddElement()[/c] markiert und den Fehler gebracht und dann hab ich
alles etwas umgestellt und dann war der Fehler bei [c]ReadStructure()[/c].
Aber es wäre ja wohl schlauer, wenn er die entsprechende Zeile in
[c]ReadStructure()[/c] markiert, die zuweit liest.

Verfasst: 27.02.2006 21:56
von remi_meier
Komisch, beim entfernen eines 'd's gabs bei mir wieder Fehler, aber egal,
anscheinend läufts ja jetzt :)

Verfasst: 28.02.2006 07:51
von shadow
Hi,

jetzt wo das angesprochen wird kann ich mich erinnern, dass ich auch Invalid Memory Access Fehler bei meinem SQLite Wrapper hatte. Damals dachte ich, dass es mit dem Funktionsaufruf wegen einem falsch gesetzten Zeiger was zu tun hatte oder so.
Hier mal mein Code der Callback:

Code: Alles auswählen

;- Struktur für einen Datensatz (max. 20 Spalten)
Structure SRecordSet
  StructureUnion
    Column.l[20]
    Record.s[20]
  EndStructureUnion
EndStructure
; Liste mit dem aktuellen ResultSet (aktuelle Datensätze)
NewList ResultSet.SRecordSet()
;************************************************************************
; Callback-Routine für die Datenbank.
;************************************************************************
Procedure.l DBCallback(*parg.s, argc.l, argv.l, col.l)
  ; PB meldet ab und zu einen Speicherzugriffsfehler beim verlassen dieser 
  ; Funktion. Durch Tests weiß ich jedoch, dass diese Fehlermeldungen an 
  ; sich nichts zu sagen haben. Deswegen wird das Fehlerhandling für die 
  ; Dauer dieser Funktionsausführung übersprungen...
  ; -----------------------------------------
  ; WICHTIG:
  ; Keine Ahnung warum, aber beim direkten Zugriff über die LinkedList meldet
  ; der Compiler Speicherzugriffsfehler. Indirekt über einen Zeiger kommt nichts!!!
  *record.SRecordSet = argv
  AddElement(ResultSet())
  *result.SRecordSet = @ResultSet()
  For i = 0 To argc-1
    If *record\Column[i] <> #Null
      *result\Record[i] = PeekS(*record\Column[i])
      Debug "Spalte: " + Str(i) + " Wert: " + PeekS(*record\Column[i])
    Else
      Debug "Spalte: " + Str(i) + " Wert: "
      *result\Record[i] = ""
    EndIf
  Next i
  ProcedureReturn 0
EndProcedure
Also nur zur Erläuterung, ich wollte extra keine extra LIB verwenden. Deshalb der Workaround unter PB, damit man die Dll zur Laufzeit austauschen kann.
Das komische daran ist, dass der Zugriffsfehler nie zu einer bestimmten Zeit kommt (selbst immer mit dem selben Result).

Könnte das was damit zu tun haben? Wenn nicht, einfach ignorieren :)

Grüße