Seite 1 von 3

Schreibfehler an Adresse 46 im RAM?

Verfasst: 09.03.2011 22:30
von SebastianJu2
Was kann ich gegen folgendes tun?

Mein Skript verarbeitet 60.000 URLs. Im 2. Schritt nimmt es die URLs auseinander und speichert die Einzelteile in einer Struktur. Irgendwann, es ist immer bei einer anderen URL, stoppt der Debugger irgendwo in der Mitte der Liste und meldet:
[ERROR] Ungültiger Speicherzugriff. (Schreibfehler an der Adresse 46)
Es passiert in dieser Zeile wo ein neues Element für die Struktur angelegt wird:

Code: Alles auswählen

If Len(URL$) : AddElement(URLPartsList()) : Else : Break : EndIf 
URL$ ist immer mit einer anderen URL gefüllt und Len müsste true ergeben. Es liegt also wohl am AddElement.

Im Taskmanager sehe ich eigentlich noch genug Speicher frei und es gibt auch keine Speicherverbrauchsspitze durch das Programm. Der Prozess verbraucht in dem Moment 46MB RAM.

Die Liste ist so definiert:

Code: Alles auswählen

Structure URLParts
  *p
  Protocol.s
  List SubdomainsBackwards.s()
  Domain.s
  TLD.s
  Path.s
  Parameters.s
  AllTogetherForSearch.s
EndStructure
NewList URLPartsList.URLParts()
Wieso kommt dieser Fehler wenn doch Speicher frei ist? Kann ich da irgendetwas tun außer Daten in Dateien auszulagern oder Variablen zu leeren?

Re: Schreibfehler an Adresse 46 im RAM?

Verfasst: 09.03.2011 22:35
von ts-soft
Hat doch nichts mit dem freien Speicher zu tun. Du schreibst auf eine ungültige Adresse,
(meist ist es adresse 0).
Entweder Du postest so viel Code, das man den Fehler nachvollziehen kann, oder Du
nimmst den Debugger und Brain.exe und machst es selber.

Mit dem von Dir geposteten läßt sich der Fehler jedenfalls nicht ermitteln.

Re: Schreibfehler an Adresse 46 im RAM?

Verfasst: 09.03.2011 22:46
von SebastianJu2
Hier mal der gesamte Code. Teil zwei ab Zeile 100 macht die Probleme. Genauer gesagt Zeile 103 (Dem Code-Tag täte eine Numerierung vorn dran ganz gut.):

Code: Alles auswählen

EnableExplicit

;Consts
#ProgressUpdateInterval = 100 ;ms

;Structures
Structure Pointer
  *p
EndStructure
Structure URLParts
  *p
  Protocol.s
  List SubdomainsBackwards.s()
  Domain.s
  TLD.s
  Path.s
  Parameters.s
  AllTogetherForSearch.s
EndStructure

;Handles
Define *HandleWindowMain, *HandleEditorURLInput, *HandleListIconOutput
Define *HandleButtonInputToOutput, *HandleTextInputToOutputProgress
Define *HandleButtonClipboardToInput

;Vars
Define.i EventID, ProgressCounterChar, ProgressCounterURL, InputStringLength
Define.i LastTimestamp, ListNumberOfElements, x, y
Define.s URLInputList$, URL$, Cache$, OldStatusInputToOutputProgress$
Define *Char.Character, *LastChar.Character
Dim *URLList(1)
NewList URLPartsList.URLParts()

Procedure Msg(Msg$,Type.a = 1)
Define Type$
  If Not Type : Type$ = "Error" : Else : Type$ = "Message" : EndIf
  MessageRequester(Type$, Type$+": " + Msg$, 0)
  If Not Type : End : EndIf
EndProcedure

Procedure ChkCreated(*Handle, Type$, Action$ = "create", Addition$ = "")
  If Not *Handle : Msg("Couldnt " + Action$ + " " + Type$ + " " + Addition$, 0) : End : EndIf
EndProcedure

Macro ListAdd(List,Value) : AddElement(List) : List = Value : EndMacro
Macro ListAddS(List,Value) : AddElement(List) : List\s = Value : EndMacro
Macro ListAddP(List,Value) : AddElement(List) : List\p = Value : EndMacro

*HandleWindowMain = OpenWindow(#PB_Any, 0, 0,700, 400, "URLTool", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_ScreenCentered)
ChkCreated(*HandleWindowMain,"Window")
*HandleEditorURLInput = EditorGadget(#PB_Any, 5, 5, 600, 150)
*HandleButtonClipboardToInput = ButtonGadget(#PB_Any, 620, 10, 70, 60, "Take URLs from Clipboard", #PB_Button_MultiLine )
*HandleButtonInputToOutput = ButtonGadget(#PB_Any, 5, 167, 30, 30, "V", #PB_Button_MultiLine)
*HandleTextInputToOutputProgress = TextGadget(#PB_Any, 50, 175, 555, 20, "",#PB_Text_Border)
*HandleListIconOutput = ListIconGadget(#PB_Any, 5, 210, 600, 185, "URL", 595)

Repeat
  EventID = WaitWindowEvent()
  
  If EventWindow() = *HandleWindowMain And EventID = #PB_Event_Gadget
    
    If EventGadget() = *HandleButtonClipboardToInput
      SetGadgetText(*HandleEditorURLInput, GetClipboardText())
    EndIf
    
    If EventGadget() = *HandleButtonInputToOutput
      
      ;Read URLs
      URLInputList$ = GetGadgetText(*HandleEditorURLInput)
      InputStringLength = Len(URLInputList$)
      *Char = @URLInputList$
      *LastChar = @URLInputList$
      FreeArray(*URLList())
      Dim *URLList(1000)
      *URLList(0) = *Char
      LastTimestamp = ElapsedMilliseconds()
      ProgressCounterChar = 0
      ProgressCounterURL = 0
      Repeat
        ProgressCounterChar + 1
        If *Char\c = 10 Or *Char\c = 13
          *Char\c = 0
        ElseIf *LastChar\c = 0
          ProgressCounterURL + 1
          If (ProgressCounterURL + 1) % 1000 = 0 : ReDim *URLList(ProgressCounterChar + 1) : EndIf  
          *URLList(ProgressCounterURL) = *Char
        EndIf
        *LastChar = *Char
        *Char + SizeOf(Character)
        If (ElapsedMilliseconds() - LastTimestamp) > #ProgressUpdateInterval
          SetGadgetText(*HandleTextInputToOutputProgress, "Read URLs: " + Str(ProgressCounterURL) + " - " + Str((ProgressCounterChar * 100) / InputStringLength) + "%")
          LastTimestamp = ElapsedMilliseconds()
        EndIf
      Until  *Char\c = 0
      ReDim *URLList(ProgressCounterURL + 1)
      SetGadgetText(*HandleTextInputToOutputProgress, "Read URLs: " + Str(ProgressCounterURL + 1) + " - " + Str((ProgressCounterChar * 100) / InputStringLength) + "%")
      OldStatusInputToOutputProgress$ = GetGadgetText(*HandleTextInputToOutputProgress)
      
      ;Parse URLs
      For x = 0 To ProgressCounterURL - 1
        Repeat
          URL$ = PeekS(*URLList(x))
          If Len(URL$) : AddElement(URLPartsList()) : Else : Break : EndIf 
          URLPartsList()\p = *URLList(x)
          URLPartsList()\Protocol = GetURLPart(URL$, #PB_URL_Protocol)
          Cache$ = GetURLPart(URL$, #PB_URL_Site)
          For y = CountString(Cache$,".") + 1 To 1 Step -1
            If Not URLPartsList()\TLD
              URLPartsList()\TLD = StringField(Cache$, y, ".")
            ElseIf Not URLPartsList()\Domain
              URLPartsList()\Domain = StringField(Cache$, y, ".")
            Else
              ListAdd(URLPartsList()\SubdomainsBackwards(), StringField(Cache$, y, "."))
            EndIf
          Next
          URLPartsList()\Parameters = GetURLPart(URL$, #PB_URL_Parameters)
          URLPartsList()\Path = GetURLPart(URL$, #PB_URL_Path)
          ForEach URLPartsList()\SubdomainsBackwards()
            Cache$ = URLPartsList()\SubdomainsBackwards() + Cache$
          Next
          URLPartsList()\AllTogetherForSearch = URLPartsList()\Domain + URLPartsList()\TLD + Cache$ + URLPartsList()\Protocol + URLPartsList()\Path + URLPartsList()\Parameters
          If (ElapsedMilliseconds() - LastTimestamp) > #ProgressUpdateInterval
            SetGadgetText(*HandleTextInputToOutputProgress, OldStatusInputToOutputProgress$ + " -- Parsed URLs: " + Str(x + 1) + " - " + Str(((x + 1) * 100) / ProgressCounterURL - 1) + "%")
            LastTimestamp = ElapsedMilliseconds()
          EndIf
        Until #True
      Next
      SetGadgetText(*HandleTextInputToOutputProgress, OldStatusInputToOutputProgress$ + " -- Parsed URLs: " + Str(x + 1) + " - " + Str(((x + 1) * 100) / ProgressCounterURL - 1) + "%")
      OldStatusInputToOutputProgress$ = GetGadgetText(*HandleTextInputToOutputProgress)
      
      ;Sort URLs
      SortStructuredList(URLPartsList(), #PB_Sort_NoCase | #PB_Sort_Ascending, OffsetOf(URLParts\AllTogetherForSearch), #PB_Sort_String)
      SetGadgetText(*HandleTextInputToOutputProgress, OldStatusInputToOutputProgress$ + " -- Sorted")
        
;       ProgressCounterURL = 0
;       ListNumberOfElements = ListSize(InputList())
;       ForEach InputList()
;         ProgressCounterURL + 1
; ;         AddGadgetItem(*HandleListIconOutput, 0, PeekS(InputList()\p))
;         s$ + PeekS(InputList()\p) + #CRLF$
;         If (ElapsedMilliseconds() - LastTimestamp) > 100
;           SetGadgetText(*HandleTextInputToOutputProgress2, Str((ProgressCounterURL * 100) / ListNumberOfElements) + "%")
;           LastTimestamp = ElapsedMilliseconds()
;         EndIf
;       Next
;       SetGadgetText(*HandleListIconOutput,s$)
;       SetGadgetText(*HandleTextInputToOutputProgress2, "100%")
;       
;       SetGadgetText(*HandleTextInputToOutputProgress, "")
;       SetGadgetText(*HandleTextInputToOutputProgress2, "")
    EndIf
    
  EndIf
  
Until EventID = #PB_Event_CloseWindow

Re: Schreibfehler an Adresse 46 im RAM?

Verfasst: 09.03.2011 23:09
von SebastianJu2
Soll ich noch meine URL-Liste posten?

Re: Schreibfehler an Adresse 46 im RAM?

Verfasst: 09.03.2011 23:21
von ts-soft
SebastianJu2 hat geschrieben:Soll ich noch meine URL-Liste posten?

Code: Alles auswählen

Dim *URLList(1)
Dim *URLList(1000)
FreeArray(*URLList())
Was soll das sein? Einem Pointer dimmen, wo gibt es den sowas?
Ich sag da aber nichts mehr zu, ich hatte es schon alles gesagt.

Re: Schreibfehler an Adresse 46 im RAM?

Verfasst: 09.03.2011 23:43
von SebastianJu2
Das ist ein Pointerarray. Der Stern ist doch Teil des Arraynamens. Und bei Dim sehe ich nicht dass es nicht erlaubt ist ein Pointerarray zu erstellen. Außerdem gibt es keine Fehlermeldung dass das nicht erlaubt wäre.

Und was ist mit der Speichermeldung?

Re: Schreibfehler an Adresse 46 im RAM?

Verfasst: 10.03.2011 00:04
von ts-soft
Man kann nur Variablen Dimmen, Pointer sind keine Variablen, wie oft noch.
Pointer kann man nur Speicher zuweisen.

Re: Schreibfehler an Adresse 46 im RAM?

Verfasst: 10.03.2011 00:58
von cxAlex
ts-soft hat geschrieben:Man kann nur Variablen Dimmen, Pointer sind keine Variablen, wie oft noch.
Pointer kann man nur Speicher zuweisen.

Code: Alles auswählen

Dim *Pointers(10)
Dim Pointers.i(10)

*Pointers(10) = 10
Pointers(10) = 10

Ich seh das Problem nicht. Ist einfach ein Integer-Array, und ein Pointer ist nichts anderes als ein Integer (eine 32/64 Bit Adresse) ?
Ob er das jetzt so oder so schreibt ist doch egal, wenn das Feld nur Pointer enthält finde ich diese Deklaration sogar gut, so kann man das genze gleich im Source erkennen.

Gruß, Alex

Re: Schreibfehler an Adresse 46 im RAM?

Verfasst: 10.03.2011 01:09
von SebastianJu2
Pointer sind keine Variablen. Pointer zeigen nur auf einen Speicherplatz. Und warum sollten sie nicht eine 0 zurückgeben wenn sie (noch) auf keinen Speicherplatz zeigen?
Gehts dir um die Struktur auf die der Pointer weist? Das wäre der Standard wenn nichts angegeben.
Oder worum geht es dir?
EnableExplicit verlangt auch Pointer zu definieren. Und die geben dann eben 0 zurück solange man ihnen noch keine Speicheradresse zugewiesen hat. Ich kann auch 10 Pointer definieren und alle geben 0 zurück. Oder ein Array mit 10 Pointern und alle geben erstmal nur 0 zurück.
Sag mir doch mal bitte wo festgelegt ist dass es kein Pointerarray geben darf. Und wieso es nicht einfach eine Fehlermeldung gibt wenn da was falsch dran wäre.

Re: Schreibfehler an Adresse 46 im RAM?

Verfasst: 10.03.2011 01:16
von ts-soft
Pointer sind eben keine Integer!
Bei Variablen wird automatisch der Speicher allokiert, bei Pointern eigentlich nicht,
denen weißt man bereits allokierten Speicher zu.

Das Dim mit Pointern anscheinend funktioniert ist für mich :freak:
zumindest ein schlechter Stil. Normallerweise müßte der Speicher mit
allocatememory zugewiesen werden.

Aber egal, Dim *Pointers(10) ist schlechter Stil, auch wenn es funktioniert und
macht auch nicht unbedingt Sinn.