Rücksprung über mehrere Prozeduraufrufe

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
#NULL
Beiträge: 2235
Registriert: 20.04.2006 09:50

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von #NULL »

Man kann auch den Fehler/Status als Rückgabewert, und Funktionsergebnisse über Ausgabeparameter zurückgeben.

Code: Alles auswählen

Procedure.i f(x.i, *out.Integer)
  If x <= 100
    *out\i = 2 * x
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

Define xx.i

If f(3, @ xx)
  Debug "xx: " + xx
Else
  Debug "error"
EndIf

If f(300, @ xx)
  Debug "xx: " + xx
Else
  Debug "error"
EndIf

Oder auch andersherum, oder beides über Ausgabeparameter. Oder auch beides in einer Struktur (\result, \error) als Rückgabewert. Ändert aber nichts am grundlegend C-like error handling. Ich würde aber lokales handling gegenüber irgendwelchen globalen flags vorziehen.
Gab es nicht auch mal eine try/catch lib für PB? Kommt aber wahrscheinlich am Ende aufs Selbe raus.
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von RSBasic »

#NULL hat geschrieben:Gab es nicht auch mal eine try/catch lib für PB?
Meinst du diesen Code? viewtopic.php?f=8&t=20370
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
#NULL
Beiträge: 2235
Registriert: 20.04.2006 09:50

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von #NULL »

Was ich in Erinnerung hatte war wahrscheinlich eher was hier in der purearea gelistet ist. Ich sehe aber im englischen Forum gab es da einige Versuche. Ich hab sowas selbst aber nie verwendet.
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von Josh »

Danke mal für eure zahlreichen Antworten:

@juergenkulow
Interessanter Code. Hab mich schon mal ein bisschen damit rumgespielt, damit ich überhaupt kapiere um was es da geht. Ob ich es dann auch so mache, kann ich noch nicht sagen, auf jeden Fall will ich mal ein paar Tests machen.

Code: Alles auswählen

MOV rsp,rsp_reg
MOV rax,rip_reg 
JMP rax ; Springe zur Fehlerbehandlung
Was ich noch nicht verstehe, warum stellst du die Sprungadresse zuerst in ein Register? Würde der folgende Code nicht das gleiche machen?

Code: Alles auswählen

MOV rsp,rsp_reg
JMP rip_reg
@GPI
Ja, das war mir schon klar geworden, dass ohne EndProcedure / ProcedureReturn ein paar Probleme auftauchen könnten. Ich muss mir mein eigenes Programm mal genauer ansehen, ich glaube, dass in den betroffenen Prozeduren keine Array, Lists und Maps erstellt werden. Da wird nur Daten aus der bereits geöffneten Datei gelesen und diese Daten dann in aufbereiteter Form in globale Listen und Maps gestellt. Lokale Variablen dürften nach meiner Meinung ja kein Speicherleck hinterlassen, wenn ich die Prozedur ohne EndProcedure bzw. ProcedureReturn verlasse (Wichtig: Falls ihr anderer Meinung seid, bitte posten). Zur Zeit habe ich das auch über ein Macro gelöst, um die Rücksprünge möglichst übersichtlich zu halten. Wie schon zu Jürgen gesagt, ich muss mir das ganze mit ASM erst mal ansehen.


@¯\_(ツ)_/¯
Bitte erschlag mich nicht, wenn es nicht stimmt. Habe auch keine Ahnung von ASM und hab mich auch erst ein wenig einlesen müssen:

Code: Alles auswählen

MOV rsp,rsp_reg ; Setzt den Stackpointer auf die vorher gemerkte Adresse zurück
MOV rax,rip_reg ; Stellt die Sprungadresse ins Register rax
JMP rax         ; Springe zur Fehlerbehandlung
DarkDragon
Beiträge: 6267
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von DarkDragon »

Bei sowas wäre ich allerdings sehr vorsichtig, denn Speicherbereiche und Objekte werden ggf. nicht mehr automatisch durch PB aufgeräumt. Man stelle sich sowas vor:

Code: Alles auswählen

Procedure C()
  Throw ; Springe zu A zurück
EndProcedure

Procedure B()
  ; Die Variablen liegen dann auf dem Stack, der aber einfach wieder zurückgesetzt wird, und Pointer auf Heapobjekte sind dann für immer verloren:
  Protected *Memory = AllocateMemory(1024)
  Protected String.s = "Ich weiß nicht" + #LF$ + "was mit solchen Strings passieren würde"
  Protected Font.i = LoadFont(#PB_Any, "Arial", 16)
  
  C()
EndProcedure

Procedure A()
  Try
  B()
  Catch
  ; Hier wurde nun einfach der Stack und Instruction Pointer zurückgesetzt.
  ; - *Memory wurde nicht freigegeben und der Pointer ist auch verloren.
  ; - Es ist mir unklar was mit dem String passiert (kenne die Internas aktuell nicht)
  ; - Der Font wäre auch verloren, genau wie andere PB Objekte.
  EndTry
EndProcedure

A()
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von mk-soft »

Ich finde #NULLs Methode mit den Rückgabewert als Status noch am besten.
Ist eigentlich oft auch bei API-Funktionen so oder bei Objektprogrammierung als Result #S_OK oder der Fehlercode.

Man muss sich nur daran gewöhnen das man bei PB nicht mehr Strings verwendet, sondern String-Pointer...

Code: Alles auswählen


#P_Ok = 0

Enumeration Errors $80000000 Step 1
  #Err_OutOfMemory
  #Err_Pointer
  ; etc
EndEnumeration

Define LastError

Procedure Foo(Var.i, *Result.String)
  Shared LastError  
  If *Result = 0
    LastError = #Err_Pointer
    ProcedureReturn LastError
  EndIf
  
  *Result\s + Str(Var)
  
  ProcedureReturn #P_Ok
EndProcedure

Define t1.String\s ; = "Value = "

r1 = Foo(100, @t1)
If r1 = #P_Ok
  Debug t1\s
Else
  Debug "Errorcode: " + Hex(r1)
EndIf

r1 = Foo(100, @t1)
If foo(200, 0)
  Debug "LastError: " + Hex(LastError)
Else
  Debug t1\s
EndIf
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von GPI »

Josh hat geschrieben: @GPI
Ja, das war mir schon klar geworden, dass ohne EndProcedure / ProcedureReturn ein paar Probleme auftauchen könnten. Ich muss mir mein eigenes Programm mal genauer ansehen, ich glaube, dass in den betroffenen Prozeduren keine Array, Lists und Maps erstellt werden.
Ich kann mir vorstellen, das Strings auch Probleme machen. Wie gesagt, keiner hier weis, wie PB das alles intern behandelt. Und ich bin noch nie ein großer Fan davon gewesen, Assembler a) so tiefgreifend zu benutzen und b) wenn man Assembler nicht selber kann :)
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: Rücksprung über mehrere Prozeduraufrufe

Beitrag von Josh »

Ja, ihr habt natürlich recht, Strings würden Probleme machen, da bin ich mir fast zu 100% sicher. Also ist das ganze mit dem Zurücksetzen des Stacks hinfällig.

Danke allen für die Antworten, war trotzdem interessant ein bisschen reinzugucken, was man mit ASM alles machen kann.
Antworten