[Falsch-Verwendung] Parameter-Übergabe: String

Fragen und Bugreports zur PureBasic 4.0-Beta.
Benutzeravatar
Leonhard
Beiträge: 602
Registriert: 01.03.2006 21:25

[Falsch-Verwendung] Parameter-Übergabe: String

Beitrag von Leonhard »

Orginal-Titel: Parameter-Übergabe: String wird überschrieben
Ich hab im moment in meinem Programm einen ganz nerfigen Bug:

Der Code sieht ungefähr so aus:

Code: Alles auswählen

Structure Token
  sValue.s
EndStructure
Structure ParamX
  StructureUnion
    *token.Token
  EndStructureUnion
EndStructure

Procedure Change(*Param.ParamX)
  *Param\token\sValue = "StringReturn"
  Debug "Var.s = "+*Param\token\sValue
  Debug "@Var.s = "+Str(@*Param\token\sValue)
EndProcedure

Define pram.ParamX\token = AllocateMemory(SizeOf(Token))

Change(@pram)

Debug "Var.s = "+pram\token\sValue
Debug "@Var.s = "+Str(@pram\token\sValue)

Nur bei mir wird irgendwie der Inhalt des Speichers überschrieben, wobei ich keine Ausfürhung mache, die so etwas bewirkt. Der Debug bei mir lautet:
[09:58:05] [Debug] Var.s = lVar
[09:58:05] [Debug] @Var.s = 9128904

[09:58:07] [Debug] Var.s = ????
[09:58:07] [Debug] @Var.s = 9128904
Irgendetwas muss da vom PureBasic-Compiler vertauscht werden, da alles Funktioniert, wenn ich das über eine andere Procedure arbeiten lasse.
Zuletzt geändert von Leonhard am 25.07.2007 07:18, insgesamt 1-mal geändert.
Benutzeravatar
Froggerprogger
Badmin
Beiträge: 855
Registriert: 08.09.2004 20:02

Beitrag von Froggerprogger »

Hier ist alles wie erwartet. Ausgabe:

Code: Alles auswählen

Var.s = StringReturn
@Var.s = 28771944
Var.s = StringReturn
@Var.s = 28771944
Ich nutze PB 4.02 unter Windows
!UD2
Benutzeravatar
Leonhard
Beiträge: 602
Registriert: 01.03.2006 21:25

Beitrag von Leonhard »

Ich weiß, das der Code funktioniert. Bei mir funktioniert er auch. Der Code ist so ähnlich wie in meinem Programm aufgebaut, und da funktioniert das nicht.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

:lol: törööö
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Little John

Beitrag von Little John »

Leonhard hat geschrieben:Ich weiß, das der Code funktioniert. Bei mir funktioniert er auch. Der Code ist so ähnlich wie in meinem Programm aufgebaut, und da funktioniert das nicht.
<Loriot-Modus>
Aha.
</Loriot-Modus>

SCNR, Little John
Benutzeravatar
Vallan
Beiträge: 223
Registriert: 20.01.2006 19:34
Kontaktdaten:

Beitrag von Vallan »

dann Poste doch mal einen Code bei dem es nicht geht.
(oder hast du was üersehen?)
Benutzeravatar
Leonhard
Beiträge: 602
Registriert: 01.03.2006 21:25

Beitrag von Leonhard »

Der gesamte Code ist etwas zu lang (mehr als 1500 Zeilen). Ich kann hier mal einen Code-Abschnitt rein setzten (cg_sec_code_set(...) ist die Start-Procedure):

Code: Alles auswählen

Procedure cg_sec_code_Expression(iFile.l, *scSection.PL_Section, *ReturnParam.pp_Parameter)
  Protected NewList Parameter.pp_Parameter()
  Protected *tmpParam.pp_Parameter
  
  While *tmpPPToken\sCommand <> "END_EXPRESSION"
    Debug *tmpPPToken\sCommand
    Debug *tmpPPToken\Param1\tToken\sValue
    Debug *tmpPPToken\Param2\tToken\sValue
    Debug "  "+*tmpPPToken\sCommand+" ('"+cg_asm_GetParamString(*scSection, @*tmpPPToken\Param1)+"', '"+cg_asm_GetParamString(*scSection, @*tmpPPToken\Param2, #True)+"')"
    If *tmpPPToken\sCommand = "TOKEN" ;/ Letzeter Token nach Expression
      AddElement(Parameter())
      Parameter()\bType = #PPT_Token
      CopyMemory(*tmpPPToken\Param1\tToken, @Parameter()\tToken, SizeOf(Token))
      Debug "ByCopy(1): "+Parameter()\tToken\sValue
    Else
      If cg_param_IsParma(*tmpPPToken\Param2) ;/ Wenn zwei Parameter angegeben werden, wird ein neuer Register benötigt.
        AddElement(Parameter())
        Parameter()\bType = #PPT_AsmReg
        Parameter()\Reg = cg_asm_GetReg(wCPU_Bit)
        
        cg_asm_mov(iFile, *scSection, @Parameter(), @*tmpPPToken\Param1)
        *tmpParam = @*tmpPPToken\Param2
      Else
        *tmpParam = @*tmpPPToken\Param1
      EndIf
      
      Select *tmpPPToken\sCommand
        Case "+" : cg_asm_add(iFile, *scSection, @Parameter(), *tmpParam) ; : cg_asm_ADD(iFile, @*tmpPPToken\Param1, @*tmpPPToken\Param2, @*tmpReg())
        Case "-"
        Case "*" : cg_asm_mul(iFile, *scSection, @Parameter(), *tmpParam) ; : cg_asm_MUL(iFile, @*tmpPPToken\Param1, @*tmpPPToken\Param2, @*tmpReg())
        Case "/"
        Default
          Debug "Unbekannter Befehl (in Bedingung): '"+*tmpPPToken\sCommand+"'"
          CallDebugger
      EndSelect
    EndIf
    
    NextPPToken(*scSection\plInsideLanguage)
  Wend
  
  If CountList(Parameter()) > 1
    ForEach Parameter()
      If ListIndex(Parameter()) <> 0
        cg_asm_FreeReg(Parameter()\reg)
      EndIf
    Next Parameter()
  EndIf
  
  CopyMemory(@Parameter(), *ReturnParam, SizeOf(pp_Parameter))
  Debug "@Var.s = "+Str(@*ReturnParam\tToken\sValue)
  Debug "Var.s = "+*ReturnParam\tToken\sValue
  
  CallDebugger
EndProcedure

; '='
Procedure cg_sec_code_set(iFile.l, *scSection.PL_Section, sReg.s = "") ;/ Setzt Variable oder in Register, wenn angegeben
  Protected *tmpParam2.pp_Parameter
  If Len(sReg)
    *tmpParam2.pp_Parameter = AllocateMemory(SizeOf(pp_Parameter))
    *tmpParam2\bType = #PPT_AsmReg
    *tmpParam2\Reg = cg_asm_GetReg(32, sReg)
    If *tmpParam2\Reg = 0
      Debug "Register '"+sReg+"' ist nicht verfügbar!"
      CallDebugger
      End
    EndIf
  Else
    *tmpParam2 = *tmpPPToken\Param1
  EndIf
  
  NextPPToken(*scSection\plInsideLanguage)
  
  Protected *tmpParam.pp_Parameter = AllocateMemory(SizeOf(pp_Parameter))
  cg_sec_code_Expression(iFile, *scSection, *tmpParam)
  Debug "Var.s = "+*tmpParam\tToken\sValue
  Debug "@Var.s = "+Str(@*tmpParam\tToken\sValue)
  ;Debug "Return("+Str(*tmpParam)+"): "+*tmpParam\tToken\sValue
  
  CallDebugger
  
  cg_asm_mov(iFile, *scSection, *tmpParam2, *tmpParam)
  
  If *tmpParam\bType = #PPT_AsmReg
    cg_asm_FreeReg(*tmpParam\reg)
  EndIf
  FreeMemory(*tmpParam)
  If Len(sReg)
    cg_asm_FreeReg(*tmpParam2\reg)
    FreeMemory(*tmpParam2)
  EndIf
EndProcedure

Procedure cg_sec_code(iFile.l, *scSection.PL_Section)
  Select *tmpPPToken\sCommand
    Case "="
      cg_sec_code_set(iFile, *scSection)
    Case "RETURN"
      cg_sec_code_set(iFile, *scSection, "eax")
      WriteStringN(iFile, "    CALL s@"+Str(*scSection\lNr)+"@return")
      ;cg_sec_code_call_return(iFile, *scSection)
    Default
      Debug "Unbekannter Befehl: '"+*tmpPPToken\sCommand+"'"
      CallDebugger
  EndSelect
EndProcedure
Kannst mich ja wegen dem Code noch mal befragen, wenn du etwas nicht verstehst.
Zuletzt geändert von Leonhard am 16.05.2007 06:43, insgesamt 1-mal geändert.
Benutzeravatar
Froggerprogger
Badmin
Beiträge: 855
Registriert: 08.09.2004 20:02

Beitrag von Froggerprogger »

Bevor man etwas als Bug postet, sollte man den Fehler einkreisen und dann mit einer genauen Beschreibung und lauffähigem Beispiel posten. Viele Bugs entpuppen sich nachher einfach als teils bös versteckte Programmierfehler.

Dass cg_sec_code_set(...) die Startprozedur ist bringt mir wenig, da ich nicht weiß, was ich der übergeben soll. Und so wie du schreibst ("Ich kann hier mal einen Code-Abschnitt rein setzten") ist nichteinmal geklärt, ob dieser Ausschnitt überhaupt irgendwas mit dem 'Bug'zu tun hat.

Versuch doch mal, den Fehler exakt zu bestimmen! :allright:
!UD2
Benutzeravatar
Leonhard
Beiträge: 602
Registriert: 01.03.2006 21:25

Beitrag von Leonhard »

Eins kann ich dir 100% versichern: Das ist ein Bug. Der selbe ist mir schon mal bei Macros aufgetreten. Dann musste ich das Macro 2 mal in den Quellcode schreiben und dann hat es funktioniert.

Also zur Fehlerbeschreibung:
Ich bin dabei, einen Compiler zu schreiben. Dies sind zwei Proceduren von der Code-Generation.

*scSection\plInsideLanguage ist eine Liste, die lauter PostParser-Token enthält. Zum aufruf sieht das so aus:
Command: '=' Param1: 'Var'
Command: '*' Param1: '2' Param2: '8'
Command: '+' Param1: '10'
Command: 'END_EXPRESSION'
Command: 'Return'
Command: 'TOKEN' Param1: 'lVar'
Command: 'END_EXPRESSION'
Jetzt wird der Code der Sektion in cg_sec_code(...) generiert.
Zuerst wird der Token '=' erkannt und die Procedure cg_sec_code_set(...) wird aufgerufen. Diese findes heraus, das eine Variable gesetzt werden soll und speichert diese in *tmpParam2. Danach wird Die Procedure cg_sec_code_Expression(..., *tmpParam) aufgerufen, wobei *tmpParam die Rückgabe ist. Der erste Ausdruck enthält als Rückgabe einen Register, daher ist die Debug-Ausgabe:
[09:58:05] [Debug] Var.s =
[09:58:05] [Debug] @Var.s = 0

[09:58:07] [Debug] Var.s =
[09:58:07] [Debug] @Var.s = 0
Beim zweiten durchlauf wird bei cg_sec_code(...) erkannt, das das Keyword 'Return' aufgerufen wurde. Dabei wird der Register 'eax' mit dem ausdrück beschrieben und die Programm-Funktion beendet sich. Nun, jetzt wird erkannt, das der Register 'eax' benötigt wird. Dieser wird von cg_sec_code_set(...) auf 'benutzt' gesetzt (mit cg_asm_GetReg(...)). Danach wird wie gewöhnlich die Ausdrucks-Procedure aufgerufen. Nur jetzt ist die Debug-Ausgabe wir im oberen Post beschieben:
[09:58:05] [Debug] Var.s = lVar
[09:58:05] [Debug] @Var.s = 9128904

[09:58:07] [Debug] Var.s = ????
[09:58:07] [Debug] @Var.s = 9128904
THEEX
Beiträge: 804
Registriert: 07.09.2004 03:13

Beitrag von THEEX »

Leo,
Du mußt wohl noch einiges lernen... Gehn wir mal davon aus, daß es wirklich ein Bug ist, dann frag ich Dich, wie soll einer von uns den Fehler finden, wenn der gepostete Code ohne Fehler lauffähig ist?

Desweiteren, wenn der Code nicht das macht, was er soll, sollte man wie schon erwähnt, ein einfaches Beispiel coden, bei dem der vermutete fehlerhafte Code drin steckt. Und Du wirst es nicht glauben, oft tritt da der Fehler auf einmal nicht mehr auf, was die Möglichkeit sehr wahrscheinlich macht, daß man den Fehler an der falschen Stelle sucht. Auch kann es vorkommen, daß Grunsätzlich in den einzelnen Codeabschnitten kein Fehler drin steckt, zumindest wenn man die verschiedenen Bereiche für sich nimmt, aber oft entstehn Fehler eben dann im Zusammenhang mit dem Ganzen!

So, wenn nun aber auch in einem einfachen Beispiel der Fehler vpr kommt, dann ist es eventuell naheliegend, daß es an PureBasic liegt.
Gesperrt