Error allocating memory

  • Hi,

    ich habe ein kleines ping-Programm geschrieben, um die ping-Werte zu protokollieren.
    Je nach Rechner dauert es unterschiedlich lange, aber irgendwann kommt der Fehler "Error allocating memory", auf meinem Rechner kommt er nach ca. 10 h.

    Ich habe schon so manches umgestellt, aber der Fehler bleibt.
    Sowohl das Speichern der Werte in einer Variablen scheint nicht der Fehler zu sein und auch nicht das Anzeigen der Werte in der Listbox.

    Spoiler anzeigen
    [autoit][/autoit] [autoit][/autoit] [autoit]

    ; ===========================================================================================
    ;
    ; Script Information
    ;
    ; Title: PingYou
    ; Author: Guido Eink
    ; Description: Per Ping wird die Erreichbarkeit überprüft
    ; Version: 0.1
    ; Datum: 28.03.2013
    ;
    ; Änderungen
    ; 28.03.2013 0.2 Bugfix Zeit "0" = Zeitüberschreitung
    ; 02.04.2013 0.3 Umstellung auf manuelles Speichern
    ; 03.04.2013 0.4 ping Werte nicht ins Array schreiben, sondern in eine normale Variable
    ; 03.04.2013 0.5 ms als Status anzeigen
    ; 05.04.2013 0.6 Anzeige-ms erfassen, Löschen-Butten entfernt
    ; ===========================================================================================

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;Konstanten und Variablen für die GUI
    #include <GUIConstants.au3>
    ;Statusbar
    #include <GuiStatusBar.au3>
    ;Datei speichern
    #include <File.au3>
    ;Uhrzeit anzeigen
    #Include <Date.au3>
    ;Array
    #include <Array.au3>
    ;Listenansicht
    #Include <GuiListView.au3>
    ;Datum
    #Include <Date.au3>
    ;Netzwerk
    #include <iNet.au3>
    ;Button verändern
    #include <GuiButton.au3>
    ;Liste sortieren
    #Include <GuiListView.au3>
    ;#include <GUIConstantsEx.au3>

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;Fenster erstellen
    $hgui = GUICreate("PingYou - 0.6",600,400)
    GUISetBkColor("0xFFFFCA")

    [/autoit] [autoit][/autoit] [autoit]

    ;Globale Variablen
    ;Statusbar
    Global $hstatus
    ;Tabelle
    Global $list_ping
    ;Speicherpfad
    Global $logpfad
    ;Anzahl Zeilen
    Global $anzRow
    ;Liste speichern
    Global $col_ping

    [/autoit] [autoit][/autoit] [autoit]

    _statusbar()

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;Statusbar
    Func _statusbar()
    Local $abstand, $text

    dim $a_abstand[3] = [100,240,600]
    dim $a_text[3] = [" Guido Eink","Status:", ""]

    $hStatus = _GUICtrlStatusBar_Create ($hGUI, $a_abstand,$a_text)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;Rechner-Name
    GUISetFont(9,800,0,"Arial")
    GuiCtrlCreateLabel("Name/IP:", 10, 10, 80, 20)
    GUISetFont(9,400,0,"Arial")
    $StartIP = GUICtrlCreateInput ("", 70, 10, 110, 20)
    GUICtrlSetTip(-1, "Name oder IP-Adresse eintragen")
    ;Anzeige ms
    GUISetFont(9,800,0,"Arial")
    GuiCtrlCreateLabel("Anzeigen:", 10, 40, 60, 20)
    GUISetFont(9,400,0,"Arial")
    GuiCtrlCreateLabel("> ms", 105, 45, 60, 20)
    $AnzeigenMs = GUICtrlCreateInput ("8", 70, 40, 30, 20)
    GUICtrlSetTip(-1, "In der Liste nur Werte anzeigen, die höher sind als der eingetragende Wert")
    ;Senden
    $StartButton = GUICtrlCreateButton("Start",200,10,80,20)
    GUICtrlSetTip(-1, "Scan starten")
    ;Tabelle speichern
    $SaveButton = GUICtrlCreateButton("Speichern",320,10,80,20)
    GUICtrlSetTip(-1, "Tabelle speichern")

    [/autoit] [autoit][/autoit] [autoit]

    ;Log-File
    $LogButton = GUICtrlCreateButton("Log-File",320,40,80,20)
    GUICtrlSetTip(-1, "Speicherpfad vom Log-File")

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $list_ping = GUICtrlCreateListView("", 10, 70, 497, 280);,$LVS_LIST);,$LVS_SORTDESCENDING)
    _GUICtrlListView_SetExtendedListViewStyle($list_ping,BitOR($LVS_EX_FULLROWSELECT,$LVS_EX_BORDERSELECT))

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;################## - Funktionen - #################

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    func _StartPing()
    dim $check
    dim $start
    Dim $p
    Local $zeit, $ms, $AnzMs
    Local $fehler

    $start = GUICtrlRead($StartIP)
    $AnzMs = GUICtrlRead($AnzeigenMs)

    ;scannen
    $check = Ping($start,250)

    [/autoit] [autoit][/autoit] [autoit]

    Select
    case @error = 1
    $fehler = "Offline"
    Case @error = 2
    $fehler = "Host nicht erreichbar"
    _Intervall("Ende")
    Case @error = 3
    $fehler = "Ziel unbekannt"
    _Intervall("Ende")
    Case @error = 4
    $fehler = "Host unbekannt"
    _Intervall("Ende")
    EndSelect

    $zeit = _NowDate() & " " & _NowTime(5)

    [/autoit] [autoit][/autoit] [autoit]

    if $check Then
    $ms = $check & " ms"
    if $ms >= $AnzMs Then
    GUICtrlCreateListViewItem($anzRow & "|" & $zeit & "|" & $ms,$list_ping)
    $col_ping = $col_ping & $anzRow & ";" & $zeit & ";" & $ms & @CRLF
    EndIf
    $anzRow += 1
    _GUICtrlStatusBar_SetText ($hStatus, "Nr. " & $anzRow & ": " & $ms,1)
    else
    ;$CheckErgebnis"Status","An error occured with number: " & @error)
    GUICtrlCreateListViewItem($anzRow & "|" & $zeit & "|" & $fehler,$list_ping)
    $col_ping = $col_ping & $anzRow & ";" & $zeit & ";" & $fehler & @CRLF
    _GUICtrlStatusBar_SetText ($hStatus, "Status:",1)
    $anzRow += 1
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ;Liste fürs Sortieren vorbereiten
    _GUICtrlListView_RegisterSortCallBack($list_ping)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;Tabelle löschen
    Func _DeleteTabelle()
    $anzRow = 1
    $col_ping = ""

    ;Liste leeren
    _GUICtrlListView_DeleteAllItems($list_ping)
    while _gUICtrlListView_GetColumnCount($list_ping) > 0
    _GUICtrlListView_DeleteColumn($list_ping, 0)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    _GUICtrlStatusBar_SetText ($hStatus, "Status:",1)

    [/autoit] [autoit][/autoit] [autoit]

    ;Spalten generieren
    _GUICtrlListView_AddColumn($list_ping, "Nr", 60, 0)
    _GUICtrlListView_AddColumn($list_ping, "Uhrzeit", 140, 0)
    _GUICtrlListView_AddColumn($list_ping, "Messwert", 100, 2)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;Log-File schreiben
    func _writefile()
    Local $file
    Local $i

    _GUICtrlStatusBar_SetText ($hStatus, "Speichern....",1)
    If Not _FileCreate($logpfad) Then
    MsgBox(4096,"Error", " Datei konnte nicht erstellt werden Fehler:" & @error)
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    $file = FileOpen($logpfad,2)
    If $file = -1 Then
    MsgBox(0, "Error", "Datei kann nicht geöffnet werden!")
    return 0
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    FileWriteLine($file,"Nr.;Uhrzeit;Messwert")
    ;For $i = 0 to UBound($a_ping(),1)-1
    ; FileWriteLine($file,$i & ";" & $a_ping[$i][1] & ";" & $a_ping[$i][2])
    ;Next
    FileWriteLine($file,$col_ping)
    FileClose($file)
    _GUICtrlStatusBar_SetText ($hStatus, "Status:",1)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;Log-File Speicherort auswählen
    Func _LogPfad()
    Local $file

    $file = FileSaveDialog( "Dateiname", @ScriptDir, "csv (*.csv)", 16,"PingYou_" & GUICtrlRead($StartIP) & ".csv")
    If @error = 0 Then
    If StringRight($file,4) <> ".csv" Then
    FileMove($file,$file & ".csv",0)
    $file = $file & ".csv"
    EndIf
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    $logpfad = $file
    _GUICtrlStatusBar_SetText ($hStatus, $logpfad,2)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;Aufruf von Funktionen, entsprechend dem gesetzten Intervall
    Func _Intervall($todo)
    if $todo == "Start" Then ; Button Start wurde gedrückt - 1 Durchgang
    GUICtrlSetData($StartButton,"Ende")
    GUICtrlSetTip($StartButton, "Scan beenden")
    ;Buttons deaktivieren
    ;GUICtrlSetState($LogButton,$GUI_DISABLE)
    ;_startping()
    _DeleteTabelle()
    AdlibRegister("_StartPing",1000)
    Else ; Button Ende wurde gedrückt
    GUICtrlSetData($StartButton,"Start")
    GUICtrlSetTip($StartButton, "Scan starten")
    GUICtrlSetState($StartIP,$GUI_ENABLE)
    ;GUICtrlSetState($LogButton,$GUI_ENABLE)
    AdlibUnRegister('_StartPing')
    _GUICtrlStatusBar_SetText ($hStatus, "Status: ",1)
    EndIf
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;Fenster aufrufen
    GUISetState(@SW_SHOW )
    While 1
    Switch GUIGetMsg()
    case $GUI_EVENT_CLOSE
    _GUICtrlListView_UnRegisterSortCallBack($list_ping)
    GUIDelete()
    Exit
    case $StartButton
    _Intervall(_GUICtrlButton_GetText($StartButton))
    Case $SaveButton
    if $logpfad <> "" Then _writefile()
    Case $LogButton
    _LogPfad()
    case $list_ping
    _GUICtrlListView_SortItems($list_ping, GUICtrlGetState($list_ping))
    ConsoleWrite("klick " & @crlf)
    EndSwitch
    WEnd

    [/autoit]

    Ich bin echt ratlos.
    Das Programm wächst auch mächtig im Hauptspeicher, auch wenn die Werte nicht in der Variablen geschrieben oder in der Listbox angezeigt werden.

    Danke

    Grüße
    Guido

    Einmal editiert, zuletzt von ThinkCross (12. April 2013 um 07:45)

    • Offizieller Beitrag

    Hast du mal getestet, ob

    [autoit]

    $check = Ping($start,250)

    [/autoit]

    tatsächlich nach 250 ms abgebrochen wird? Nach meiner Erfahrung schert sich der Aufruf einen Dreck um den Zeitparameter. Die Funktion wird erst als beendet betrachtet, wenn Ping tatsächlich nach mehreren Versuchen die IP nicht erreicht. Und das dauert dann min 1 s. Inzwischen hat Adlib bereits den nächsten Funktionsaufruf angeschoben. Das ganze überlagert sich dann weiter und weiter.
    Wäre für mich eine schlüssige Erklärung.
    Ich halte es für einen weniger guten Weg, die anderen Rechner anzupingen, um zu wissen ob sie erreichbar sind. Einfach den Spieß umdrehen: Auf alle Clients läuft ein Programm, dass jede Minute aufwacht und ein PONG an den Server sendet. :thumbup:

  • Gut möglich, dass sich da was hochschaukelt, ich werde Adlib innerhalb der Funktion mal aufrufen kann, sozusagen rekursiv.

    Ne, das geht leider nicht.
    Das Tool stellt ja sozusagen ein Netzwerküberwachungsprogramm dar, damit ich schlechte Zeiten und Timeouts erfassen kann, dafür muss ich den ping sekündlich absetzen.

  • Der rekursive Aufruf war nicht erfolgreich gewesen.

    Nun mache ich am Anfang der Funktion ein AdlibUnRegister, in rund 8 h weiß ich mehr.

  • Ich habe grad nicht genug Zeit um mir das Script mal ganz anzuschauen, aber ein kleiner Hinweis zu AdlibRegister: Achte, dass du die Funktion nicht mehrmals in einem Intervall aufrufst, bei dem das Zeitintervall kleiner ist als die auszuführende Funktion. Ich hatte damals ein Speicherproblem das zum größten Teil durch meine fehlerhafte Anwendung von AdlibRegister aufgetreten ist.

    Grüße

    Grüße Yaerox

    Grüne Hölle

  • Kommentiere mal Zeile 153 ("_GUICtrlListView_RegisterSortCallBack($list_ping)") aus.
    So wie ich das sehe wird da aller einer Sekunde die Callback-Funktion registriert aber die vorhergehende nicht deregistriert.

    Mit sowas hab ich gerechnet ;)

    Grüße Yaerox

    Grüne Hölle

  • Volltreffer!
    Das Programm läuft seit über 13 h, tatsächlich lag es an Zeile 153
    Zeile 153 ("_GUICtrlListView_RegisterSortCallBack($list_ping)")

    Vielen Dank für eure Hilfe.

    Grüße
    Guido