Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Domso
Anmeldungsdatum: 02.02.2011 Beiträge: 109
|
Verfasst am: 21.06.2014, 17:59 Titel: Frage zu input |
|
|
Hallo,
ich habe gerade gerade ein paar probleme mit input;
also nicht mit dem befehl an sich, sondern mit einer Art nebeneffekt
Beim herumprobieren mit Vererbung und Strings (s. http://forum.qbasic.at/viewtopic.php?p=105124#105124 ), hatte ich des öffteren abstürze und komischerweise war der "input" befehl meistens dran schuld o0
zumindest glaube ich das.
Code: |
type myudt extends object
a as integer=1
b as Integer=2
End Type
Dim As myudt Ptr tudt =New myudt
Dim As myudt Ptr tudt2=New myudt
dim tstring as string
tstring = space(sizeof(myudt))
for x as integer = 0 to sizeof(myudt) - 1
tstring[x] = cast(UByte Ptr,Cast(Any Ptr,tudt))[x]
next
Print "|"+tstring+"|"
Sleep
|
soweit funktikoniert auch alles; doch wenn ich nun am ende nach dem sleep
Code: |
Dim As String text
Input text
|
eigentlich sollte das doch überhaupt nichts ändern, aber wenn man die ausgabe mit und ohne input vergleicht sieht man, dass der anfang (also ich vermute mal der teil von "extends object") verschieden ist?
wie kann das sein? das objekt wird ja eigentlich nur durch input verändert?
 |
|
Nach oben |
|
 |
nemored

Anmeldungsdatum: 22.02.2007 Beiträge: 4704 Wohnort: ~/
|
Verfasst am: 21.06.2014, 19:53 Titel: |
|
|
Kann das Problem vielleicht an der Konsole liegen? Ich kann den von dir beschriebenen Effekt nicht beobachten, allein schon weil mir sowohl vor als auch nach dem INPUT nichts zwischen den senkrechten Strichen angezeigt wird (also "||").
Ich habe es anders probiert:
Code: | for i as integer = 0 to len(tstring)-1
print hex(tstring[i]);
next |
und da ändert sich bei mir in der Anzeige nichts.
Ich schätze, dass die Ausgabe der Sonderzeichen bei dir irgendwas Unanständiges mit der Konsole anstellt. _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
 |
Domso
Anmeldungsdatum: 02.02.2011 Beiträge: 109
|
Verfasst am: 21.06.2014, 20:40 Titel: |
|
|
welche fb version benutzt du?
ich habe jetzt mal das problem bisschen spezifiziert und in 2 programme gepackt
das erste programm speichert den string in eine datei ab und das zweite baut aus diesem wieder den UDT zusammen.
das zweite programm stürzt sofort ab, wenn es versucht eine methode der oberklasse aufzurufen
ohne input am ende funktioniert es problemlos
Code: |
Type rootUDT extends object
As Integer var1=5
Declare Sub foo
Declare virtual function foo2 As String
End Type
Sub rootUDT.foo
Print foo2
End Sub
function rootUDT.foo2 As String
Return "test"
End Function
type myudt extends rootUDT
a as Integer=1
b as Integer=2
Declare virtual Function foo2 As String
End Type
function myudt.foo2 As String
Return "test"&a
End Function
Dim As myudt Ptr tudt =New myudt
dim tstring as string
tstring = space(sizeof(myudt))
for x as integer = 0 to sizeof(myudt) - 1
tstring[x] = cast(UByte Ptr,Cast(Any Ptr,tudt))[x]
Next
Dim As Integer f = freefile
Open "tmp" For Binary As #f
Put #f,,tstring
Close #f
Sleep
|
und
Code: |
Type rootUDT extends object
As Integer var1=5
Declare Sub foo
Declare virtual function foo2 As String
End Type
Sub rootUDT.foo
Print foo2
End Sub
function rootUDT.foo2 As String
Return "test"
End Function
type myudt extends rootUDT
a as Integer=1
b as Integer=2
Declare virtual Function foo2 As String
End Type
function myudt.foo2 As String
Return "test"&a
End Function
Dim As myudt Ptr tudt =New myudt
dim tstring as string
tstring = space(sizeof(myudt))
Dim As Integer f = freefile
Open "tmp" For Binary As #f
get #f,,tstring
Close #f
For x as integer = 0 to sizeof(myudt) - 1
cast(UByte Ptr, Cast(Any Ptr,tudt))[x] = tstring[x]
next
Print tudt->a 'funktioniert ohne probleme
tudt->foo 'funktioniert nur ohne input
Sleep
Dim As String text
Input text
|
edit: ich vermute dass am anfang des Strings die vererbungsinfos stehen und diese verändert werdenm wodurch er die dann irgendwie überschreibt |
|
Nach oben |
|
 |
nemored

Anmeldungsdatum: 22.02.2007 Beiträge: 4704 Wohnort: ~/
|
Verfasst am: 22.06.2014, 00:29 Titel: |
|
|
Wenn ich aus dem letzten Quellcode das INPUT rausnehme, stürzt es mir trotzdem ab:
Code: | Aborting due to runtime error 12 ("segmentation violation" signal) in test.bas::FOO() |
fbc 0.90.1, Linux Debian.
Könnte sein, dass ein unerlaubter Speicherzugriff stattfindet, der bei dir erst einmal unbemerkt bleibt und erst beim INPUT zur Geltung kommt. Ich kenne mich nur leider bei den Pointer-Geschichten nicht wirklich gut aus. _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
 |
Muttonhead

Anmeldungsdatum: 26.08.2008 Beiträge: 565 Wohnort: Jüterbog
|
Verfasst am: 22.06.2014, 08:04 Titel: |
|
|
ich vermute mal das die Adressen der Methoden ja erst zur Laufzeit im UDT verdrahtet werden.
Wenn du im 2.Programm den kompletten Inhalt eines UDTs überschreibst, "restaurierst" du die Adressen die fürs erste
Programm zur Laufzeit gültig waren, im grade laufenden 2.Programm aber ins Nirwana zeigen.
Mutton |
|
Nach oben |
|
 |
Domso
Anmeldungsdatum: 02.02.2011 Beiträge: 109
|
Verfasst am: 22.06.2014, 11:58 Titel: |
|
|
Zitat: | ich vermute mal das die Adressen der Methoden ja erst zur Laufzeit im UDT verdrahtet werden.
Wenn du im 2.Programm den kompletten Inhalt eines UDTs überschreibst, "restaurierst" du die Adressen die fürs erste
Programm zur Laufzeit gültig waren, im grade laufenden 2.Programm aber ins Nirwana zeige |
hmm eigentlich dürfte das aber nicht passieren, weil sizeof funktionen nicht berücksichtigt und sollten damit ja auch nicht im String auftauchen (werden ja auch nicht direkt im ram abgespeichert)
@nemored
wer achtet schon auf compiler meldungen keine ahnung, aber input wird ja eigentlich nie ausgeführt, das programm stürzt ja schon vorher ab o0
anscheinend darf man die ersten 2 byte tatsächlich nicht anfassen...
Das Problem selber lässt sich vermutlich mit
Code: | For x as integer = 2 to sizeof(myudt) - 1
cast(UByte Ptr, Cast(Any Ptr,tudt))[x] = tstring[x]
next |
lösen, aber das ändert nichts daran, warum er das überhaupt macht;
ich denke mal da müsste man die genaue implementierung in fbc kennen, um den fehler zu finden  |
|
Nach oben |
|
 |
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1279 Wohnort: Ruhrpott
|
Verfasst am: 22.06.2014, 12:59 Titel: |
|
|
Ich habe mal versucht, das Ganze ein bisschen aufzudröseln. Also: Der Datentyp "myudt" hat eine Länge von 12 Bytes, wobei die oberen 8 Bytes die Variablen a und b enthalten.
Die unteren 4 Bytes enthalten (hier auf meinem Rechner) einen Wert von 4263972 ohne "Input", einen Wert von 4276264 mit "Input" und nachfolgender Textvariable und einen Wert von 4292648 mit "Input" und nachfolgender Integervariable.
Ohne "Extends Object" in der Typendeklaration ist "myudt" 8 Bytes lang und enthält nur die Variablen a und b.
Das legt die Vermutung nahe, daß es sich bei den unteren 4 Bytes um einen Pointer oder ein Objekthandle handelt.
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
 |
MOD Fleißiger Referenzredakteur

Anmeldungsdatum: 10.09.2007 Beiträge: 1003
|
Verfasst am: 22.06.2014, 14:08 Titel: |
|
|
Der Größenunterschied ergibt sich, wie schon richtig erkannt, durch "Extends Object". Dadurch erhält dein UDT einen Pointer auf eine VTable. Wenn du jetzt durch dein UDT iterierst und den Pointer überschreibst, brauchst du dich nachher nicht über Abstürze wundern.
Der Object Pointer hängt immer am Anfang, das kannst du dir im folgenden Beispiel ansehen:
Code: | '#Define USE_EXTENDS
#IfDef USE_EXTENDS
#Define EXTEND_TYPE Extends Object
#Else
#Define EXTEND_TYPE
#EndIf
Type myudt EXTEND_TYPE
a As Long = 1
b As Long = 2
End Type
Dim As myudt tudt
Print *Cast(Long Ptr, Cast(Long Ptr, Cast(Any Ptr, @tudt)) + 0)
Print *Cast(Long Ptr, Cast(Long Ptr, Cast(Any Ptr, @tudt)) + 1)
#IfDef USE_EXTENDS
Print *Cast(Long Ptr, Cast(Long Ptr, Cast(Any Ptr, @tudt)) + 2)
#EndIf
Sleep |
Du müsstest also bei der "Extends Object"-Variante die ersten SizeOf(Any Ptr)-Bytes überspringen, dann sollte es gehen. |
|
Nach oben |
|
 |
Domso
Anmeldungsdatum: 02.02.2011 Beiträge: 109
|
Verfasst am: 22.06.2014, 16:04 Titel: |
|
|
danke für die schnelle hilfe
welche rolle der befehl input dabei gespielt hat, ist mir trotzdem noch schleierhaft (ich vermute, dass der compiler irgendetwas miteinbindet und sich dadurch das ändert) aber das ist ja nicht so wichtig |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 22.06.2014, 16:07 Titel: |
|
|
Domso hat Folgendes geschrieben: | danke für die schnelle hilfe
welche rolle der befehl input dabei gespielt hat, ist mir trotzdem noch schleierhaft (ich vermute, dass der compiler irgendetwas miteinbindet und sich dadurch das ändert) aber das ist ja nicht so wichtig |
Grundsätzlich gibt es überhaupt keine Garantie wo der vptr hinzeigt, d.h. der Wert kann bei jeder Ausführung woanders hinzeigen (vor allem bei aktiviertem ASLR, was FB aber vmtl nicht kann), oder zumindest bei jeder Neukompilierung des Programms. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1279 Wohnort: Ruhrpott
|
Verfasst am: 23.06.2014, 07:54 Titel: |
|
|
Eins verstehe ich nicht: Wieso ist das doppelte casten bei Code: | tstring[x] = cast(UByte Ptr,Cast(Any Ptr,tudt))[x] | notwendig? Warum kann tudt nicht direkt zu UByte Ptr gecastet werden?
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
 |
MOD Fleißiger Referenzredakteur

Anmeldungsdatum: 10.09.2007 Beiträge: 1003
|
Verfasst am: 23.06.2014, 08:19 Titel: |
|
|
Das liegt daran, dass der Compiler zur Compilezeit prüft, ob der Cast innerhalb der Vererbungsstruktur stattfindet und wenn nicht, einen Fehler wirft. Deswegen muss zunächst nach Any Ptr gecastet werden.
Warum das gut/schlecht ist, kannst du mit dkl im IRC Channel #fb-portal auf Freenode besprechen.  |
|
Nach oben |
|
 |
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1279 Wohnort: Ruhrpott
|
Verfasst am: 23.06.2014, 09:20 Titel: |
|
|
Zitat: | Warum das gut/schlecht ist, kannst du mit dkl im IRC Channel #fb-portal auf Freenode besprechen. | Nee, lass mal...
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 23.06.2014, 13:11 Titel: |
|
|
In Kurzform: Zwischen Typen zu casten, die "unrelated" sind, ist böse, böse, böse, und erfordert deswegen einen Umweg über einen Typ, der keinen bestimmten Typ repräsentiert. In C++ wäre das z.B. der unterschied zwischen static_cast (selbes Verhalten) und reinterpret_cast bzw C-Style casts, wo man (fast) munter casten kann, wiem an will. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1279 Wohnort: Ruhrpott
|
Verfasst am: 24.06.2014, 11:47 Titel: |
|
|
Diese Einschränkung macht doch eigentlich nur Sinn, wenn dem Compiler zum Zeitpunkt der Kompilierung die Spezifikationen des Objektes, von dem geerbt werden soll, nicht bekannt sind (oder zumindest nicht bekannt sein könnten), oder sehe ich das falsch?
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 24.06.2014, 17:57 Titel: |
|
|
grindstone hat Folgendes geschrieben: | Diese Einschränkung macht doch eigentlich nur Sinn, wenn dem Compiler zum Zeitpunkt der Kompilierung die Spezifikationen des Objektes, von dem geerbt werden soll, nicht bekannt sind (oder zumindest nicht bekannt sein könnten), oder sehe ich das falsch? |
Welche Einschränkung? Dass ein UByte und ein eigene Klasse nix miteinander zu tun haben, sieht der Compiler, ja. Deswegen klappt der Cast ja nicht. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1279 Wohnort: Ruhrpott
|
Verfasst am: 26.06.2014, 17:58 Titel: |
|
|
Ich meine die Einschränkung, daß ich einen Pointer nicht ohne Umweg von einem (Pointer-) Typ in einen anderen casten kann. Der Unterschied zwischen den verschiedenen Pointertypen besteht ja nur in der Anzahl der Bytes, die er repräsentiert (wg. Schrittweite beim Indizieren).
Entschuldigung, wenn ich hier vielleicht ein bisschen begriffsstutzig erscheine, aber für mich mit meiner Assembler-Denke hat objektorientierte Programmierung zur Zeit noch viel mystisches (Aber ich arbeite daran und gelobe Besserung ).
Mich würde in dem Zusammenhang interessieren, ob der Compiler zum Zeitpunkt der Kompilierung das "extendete" Objekt und dessen genaue Spezifikationen (und damit auch die darin enthaltenen Pointertypern) kennt oder nicht. Oder liege ich jetzt mit dem ganzen Gedankengang daneben?
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
 |
|