Rücksprung über mehrere Prozeduraufrufe

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Rücksprung über mehrere Prozeduraufrufe

Beitrag von Josh »

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
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von RSBasic »

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.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von hjbremer »

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.
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von STARGÅTE »

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.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von Josh »

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.
Benutzeravatar
juergenkulow
Beiträge: 188
Registriert: 22.12.2016 12:49
Wohnort: :D_üsseldorf-Wersten

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von juergenkulow »

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ß
Bitte stelle Deine Fragen, denn den Erkenntnisapparat einschalten entscheidet über das einzig bekannte Leben im Universum.

Jürgen Kulow Wersten :D_üsseldorf NRW D Europa Erde Sonnensystem Lokale_Flocke Lokale_Blase Orion-Arm
Milchstraße Lokale_Gruppe Virgo-Superhaufen Laniakea Sichtbares_Universum
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von Josh »

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.
Benutzeravatar
juergenkulow
Beiträge: 188
Registriert: 22.12.2016 12:49
Wohnort: :D_üsseldorf-Wersten

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von juergenkulow »

Hallo Josh,

vielleicht gibt das Progrämmchen mit viel Vorsicht ein bischen Hoffnung:

Code: Alles auswählen

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.
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von GPI »

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: Alles auswählen

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.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
¯\_(ツ)_/¯
Beiträge: 141
Registriert: 18.08.2017 09:35

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von ¯\_(ツ)_/¯ »

Moin juergenkulow,
ich kann kein ASM, kannst du mir diese Zeilen detailiert erläutern was genau passiert?

Code: Alles auswählen

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?
Bild
Antworten