Seite 1 von 3
[Falsch-Verwendung] Parameter-Übergabe: String
Verfasst: 13.05.2007 10:10
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.
Verfasst: 13.05.2007 13:26
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
Verfasst: 13.05.2007 20:42
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.
Verfasst: 14.05.2007 12:59
von Kaeru Gaman

törööö
Verfasst: 15.05.2007 17:10
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
Verfasst: 15.05.2007 21:32
von Vallan
dann Poste doch mal einen Code bei dem es nicht geht.
(oder hast du was üersehen?)
Verfasst: 15.05.2007 22:05
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.
Verfasst: 15.05.2007 23:15
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!

Verfasst: 16.05.2007 06:58
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
Verfasst: 16.05.2007 17:26
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.