PureBoard
https://www.purebasic.fr/german/

Rücksprung über mehrere Prozeduraufrufe
https://www.purebasic.fr/german/viewtopic.php?f=3&t=31101
Seite 1 von 2

Autor:  Josh [ 04.10.2018 18:53 ]
Betreff des Beitrags:  Rücksprung über mehrere Prozeduraufrufe

Mein Programm liest aus deiner Datei Daten aus und verarbeitet diese. Wenn nun in diesen ausgelesenen Daten ein Fehler auftritt, gebe ich eine Meldung aus und mein Programm setzt sich wieder in eine gewisse 'Grundstellung' zurück.

Zur Zeit handhabe ich das so, dass ich beim Auftreten eines solchen Fehlers eine globale Fehlervariable setze und die Prozedur verlasse. Da meine Prozeduren sehr verschachtelt sein können, frage ich jetzt nach jedem Prozeduraufruf ab, ob die globale Fehlervariable gesetzt ist und wenn ja, dann beende ich die eigene Prozedur. So werden die aufgerufenen Prozeduren wieder abgebaut, bis ich einen gewissen Punkt in meinem Programm erreicht habe und das Programm dort wieder in Wartestellung geht.

Das funktioniert eigentlich recht gut so, nur ist es unschön, dass ich nach jedem Prozeduraufruf diese Fehlervariable abfragen muss und ist natürlich auch gefährlich, dass ich die Abfrage mal vergesse.


Meine Frage dazu:

Habt ihr so einen Fall auch schon gehabt und wie habt ihr das mit den Fehlern bei verschachtelten Prozeduraufrufen gehandhabt. Ein Abbruch und Neustart des Programms ist keine Alternative, mein Programm muss in jedem Fall weiter laufen.


Danke schon mal

Autor:  RSBasic [ 04.10.2018 19:37 ]
Betreff des Beitrags:  Re: Rücksprung über mehrere Prozeduraufrufe

Die von dir bereits verwendete Methode ist am saubersten. Mir ist keine bessere Variante bekannt.
Bei Threads gibts KillThread. Sonst gibt es nur noch Goto. Beide sind aber nicht sauber.
Ich würde es genauso machen, wie du es bereits gemacht hast.

Autor:  hjbremer [ 04.10.2018 20:18 ]
Betreff des Beitrags:  Re: Rücksprung über mehrere Prozeduraufrufe

mit GOTO eine Procedure verlassen ist wie Selbstmord auf Raten. Irgendwann gibt es einen üblen Error :mrgreen:

Stacküberlauf, Memoryfehler etc und niemand weiß wann wieso warum.

Bei jedem Procedure Aufruf wird die Rücksprungadresse auf einen Stack abgelegt.

Bei Procedurereturn oder Endprocedure wird die Adresse vom Stack geholt. Bei Goto wohl nicht.

Autor:  STARGÅTE [ 04.10.2018 20:23 ]
Betreff des Beitrags:  Re: Rücksprung über mehrere Prozeduraufrufe

Ich schließe mich RSBasic an.

Allerdings sollte man auch noch mal überlegen, ob man evtl. einige Verschachtlungen/Rekursionen einsparen kann.

Oft können rekursiv aufgerufene Prozeduren auch als eine iterative Prozedur umgeschrieben werden, dann kannst du schneller rausspringen.

Autor:  Josh [ 04.10.2018 22:35 ]
Betreff des Beitrags:  Re: Rücksprung über mehrere Prozeduraufrufe

Eigentlich habe ich gehofft, dass es da irgendwelche schmutzigen Tricks am Stack oder so gibt :mrgreen:

Trotzdem Danke für eure Antworten. Zumindest weiß ich jetzt, dass ich nicht komplett falsch gelegen bin.

Autor:  juergenkulow [ 05.10.2018 01:01 ]
Betreff des Beitrags:  Re: Rücksprung über mehrere Prozeduraufrufe

Hallo Josh,
willkommen zum Tanz auf dem aktivem Vulkan, wenn Du Dich traust.
Bitte mache Dich mit den verschiedenen Assembler-Modellen vertraut. (x86,x64,680x0,6502,...)
Was machen die PureBasic-Befehle, wie OnErrorGoto, Compilerif, Label:, MyISP=?Label, EnabelASM, DisableASM, CreateThread genau?
Was machen die x64-ASM-Befehle genau : MOV myrsp,rsp
MOV rsp,myrsp
MOV rax,MyISP
JMP rax

Feel the ..Pure.. Power und Gruß

Autor:  Josh [ 05.10.2018 09:24 ]
Betreff des Beitrags:  Re: Rücksprung über mehrere Prozeduraufrufe

juergenkulow hat geschrieben:
Was machen die x64-ASM-Befehle genau : MOV myrsp,rsp
MOV rsp,myrsp
MOV rax,MyISP
JMP rax

Du stellst Fragen. Ganz alte Programmierer (wobei ich mir einrede, dass das 'ganz' auf mich noch nicht zutrifft) sollen sich ja mit ASM auskennen, aber da gab es noch keine x64 Prozessoren. Also folgere ich daraus, dass das keiner wissen kann :mrgreen:

Ich habe schon einiges über mein Problem gegoogelt (Pb unabhängig). Entweder hab ich noch nicht die richtigen Suchbegriffe gefunden, oder ich bin in den Weiten des Weltalls der Einzige mit diesem Problem. Im Endeffekt alles halb so schlimm, funktioniert ja mit meiner derzeitigen Lösung, aber die Hoffnung stirbt zuletzt.

Autor:  juergenkulow [ 05.10.2018 09:53 ]
Betreff des Beitrags:  Re: Rücksprung über mehrere Prozeduraufrufe

Hallo Josh,

vielleicht gibt das Progrämmchen mit viel Vorsicht ein bischen Hoffnung:
Code:
CompilerIf #PB_Processor_x64<>#PB_Compiler_Processor
  CompilerError "x64 Code"
CompilerEndIf
Global rsp_reg,rip_reg=?Fehlerbehandlung_Hauptschleife

Procedure r3() : Debug "r3" :
  EnableASM : DisableDebugger:
  MOV rsp,rsp_reg
  MOV rax,rip_reg
  JMP rax ; Springe zur Fehlerbehandlung
  DisableASM : EnableDebugger
EndProcedure
Procedure r2() : Debug "r2" : r3() : EndProcedure
Procedure r1() : Debug "r1" : r2() : EndProcedure

EnableASM : MOV rsp_reg,rsp : DisableASM
ShowAssemblyViewer() ; Auf Register Stapelverfolgung umstellen.
; Hier Haltepunkt setzten, F9 und mit F8 schrittweise verfolgen.
r1()
Fehlerbehandlung_Hauptschleife:
Debug "weiter:"

End
; Offen sind Test auf Linux und MacOS, sowie x86-Code.

Autor:  GPI [ 05.10.2018 12:37 ]
Betreff des Beitrags:  Re: Rücksprung über mehrere Prozeduraufrufe

Irgendwie kräuseln sich gerade meine Fußnägel :)
Auf keinen Fall für sowas Assembler oder ähnliche Tricks hernehmen. Da baut man sich nur die dümmsten Fehler ein. Man weis nie, was Purebasic alles bei EndProcedure und Procedurereturn so macht. Denkbar ist bspw. das man temporäre Variablen, Arrays, Listen und Maps freigegeben werden, die dann als Speicherleichen weiterleben, weil sie nie korrekt freigegeben wurden.

Mein Lösungsansatz: Macros. Damit kann man die eigentlichen Procedurenaufrufe kaschieren.
Code:
Global ErrorCode=0,ErrorLine.s

Declare _two(value)
Declare.s _one(value)
Declare ErrorHandling()

Macro SetError(err)
  If err
    ErrorCode=err
    ErrorLine="File:"+#PB_Compiler_File+" Line:"+#PB_Compiler_Line+" Procedure:"+#PB_Compiler_Procedure+" in Module "+#PB_Compiler_Module   
    CompilerIf #PB_Compiler_Procedure<>""
      ProcedureReturn
    CompilerElse
      ErrorHandling()
    CompilerEndIf
  EndIf
EndMacro
Macro CheckErrorCode()
  ;nur bei Proceduren!
  If Errorcode
    Debug "error! cancel procedure:"+#PB_Compiler_Procedure
    CompilerIf #PB_Compiler_Procedure<>""
      ProcedureReturn
    CompilerElse
      ErrorHandling()
    CompilerEndIf
  EndIf
EndMacro
Procedure ErrorHandling()
  Debug "Es ist ein Fehler aufgetreten:"+ErrorCode
  Debug ErrorLine
  End
EndProcedure



Macro One(value)
  _one(value)
  CheckErrorCode()
EndMacro
Macro two(value)
  _two(value)
  CheckErrorCode()
EndMacro


Procedure.s _One(value)
  Debug "ONE:"+value
  If value>=99
    setError(100)
  EndIf
  value+1
  two(value)
 
  ProcedureReturn ""+value
EndProcedure


Procedure _two(value)
  Debug "two:"+value
  value*2
  one(value)
  ProcedureReturn value
EndProcedure

Debug "start"
one(0)



Hat natürlich auch nachteile, die Proceduren dürfen dann nicht in IF-Statments etc. vorkommen. Ein Rückgabewert liefern sie, aber mehr verursacht vermutlich fehler.
selbst ein "variabel=ONe(10)+9" würde einen Syntax-Error auslösen.
Man könnte allerdings auf die one()/two() macros verzichten und direkt aufrufen die Proceduren _one()/_two() aufrufen, dann sollte man aber das CheckError() danach nicht vergessen.

Edit: Viele kleine Änderungen. Bspw. wird jetzt eine Variabel Errorline.s mit Information zur der Stelle gesetzt, wo seterror aufgerufen wurde. Kann beim Debuggen durchaus wichtig sein.

Autor:  ¯\_(ツ)_/¯ [ 05.10.2018 15:03 ]
Betreff des Beitrags:  Re: Rücksprung über mehrere Prozeduraufrufe

Moin juergenkulow,
ich kann kein ASM, kannst du mir diese Zeilen detailiert erläutern was genau passiert?
Code:
MOV rsp,rsp_reg
MOV rax,rip_reg
JMP rax ; Springe zur Fehlerbehandlung

Die letzte Zeile verstehe ich dank deines Kommentars aber was passiert bei den ersten zwei Zeilen genau?

Seite 1 von 2 Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/