Prototype - gefahren bei Typenkollision?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7039
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Prototype - gefahren bei Typenkollision?

Beitrag von STARGÅTE »

Tachchen,

während der arbeit mit Prototype und dem dynamischen aufrufen von Prozeduren bin ich auf seltsamme Effekte gestoße (zB. das Sprites verschwinden).

Inzwischen bin ich bei folgender Fragestellung angekommen:
Gibt es gefahren bei einer Typenkollision zwischen dem Prototyp-Rückgabetyp und dem wahren Prozedur-Pointer-Rückgabetyp?

Beispiele:
- Ich habe eine Prozedur welche eine Float zurück gibt, rufe sie aber über ein Prototyp auf der eine Integer zurückgibt.
- Ich habe eine Prozedur welche eine Integer zurück gibt, rufe sie aber über ein Prototyp auf der eine Float zurückgibt.

Scheinbar darf sowas nicht gemacht erden, auch wenn einem der Rückgabewert egal ist, scheint es Probleme im Stack zu verursachen, wie folgendes Beispiel zeigt:

Code: Alles auswählen

Procedure.f GetF(*Pointer)
	Debug "INNEN: "+Str(*Pointer)
	ProcedureReturn *Pointer
EndProcedure

Procedure.i GetI(*Pointer)
	Debug "INNEN: "+Str(*Pointer)
	ProcedureReturn *Pointer
EndProcedure

Procedure.i Beispiel(Integer.i)
	Debug "Beispiel: "+Str(Integer)
EndProcedure

Prototype.f ReturnF(*Pointer)
Prototype.i ReturnI(*Pointer)

Define f.f, i.i, *p = 16

; Alles OK
GetF_ReturnF.ReturnF = @GetF()
GetI_ReturnI.ReturnI = @GetI()
f = GetF_ReturnF(*p)
Debug f ; 16.0 richtig
i = GetI_ReturnI(*p)
Debug i ; 16 richtig

Debug "---"

; Probleme
GetF_ReturnI.ReturnI = @GetF()
GetI_ReturnF.ReturnF = @GetI()
f = GetI_ReturnF(*p)
Debug f ; NaN verständlich, ist halt müll
i = GetF_ReturnI(*p)
Debug i ; 2147340288 verständlich, ist halt müll
f = GetI_ReturnF(*p)
Debug f ; 16.0 seltsam, da der Aufruf ja der selbe ist wie beim ersten mal.
f = GetI_ReturnF(*p)
Debug f ; NaN ok, Stack wieder "frei" von ungenutzer Float von GetF_ReturnI()
Irgendwie scheint sich das auch auf andere Funktionen auszuwirken.
Daher meine Frage: Wie kann ich solch ein Problem umgehen.

Hintergrund ist:
Ich möchte eine Beliebige Prozedure ausführen (über ein Pointer), wo mit der Rückgabewert aber egal ist.

Oder führt das in jedem fall zu Speicherlecks? Weil zB eine Prozedur einen String zurück gibt. aber der Aufruf (über Prototyp) garkein string erwartet, und der dann "ungenutzt" im Speicher gleibt?

Wäre nett, wenn einer ein bisschen Licht in die Sache bringen würde.
Scheinbar ändert sich der ASM-Code:
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
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Prototype - gefahren bei Typenkollision?

Beitrag von GPI »

Die Gefahr eines Speicherlecks oder sogar Absturz ist recht groß. Wie soll der Prototype wissen, welche Werte wirklich zurück kommen. Das definiert ja gerade dieser Befehl und das ist der Sinn dahinter. Eine korrekte Typenumwandlung findet definitiv nicht statt!
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Prototype - gefahren bei Typenkollision?

Beitrag von Danilo »

STARGÅTE hat geschrieben:

Code: Alles auswählen

; Probleme
GetF_ReturnI.ReturnI = @GetF()
GetI_ReturnF.ReturnF = @GetI()
Du verwendest einen Compiler, der nach 10 Jahren noch immer keine
korrekte Typüberprüfung durchführt.
Normal würdest Du an genau dieser Stelle einen Compilerfehler
bekommen, weil die Procedure-Pointer nicht mit dem Prototype
übereinstimmen.

Sogar die Anzahl der Parameter wird nicht überprüft.

Code: Alles auswählen

Prototype.f ReturnF(*Pointer)

Global var.ReturnF

Procedure.i proc(x,y,z)
   ProcedureReturn x*y*z
EndProcedure


Procedure.i xyz()
    ProcedureReturn var(1)
EndProcedure


var = @proc()

Debug xyz()
Was soll man dazu noch sagen? :lol:
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Prototype - gefahren bei Typenkollision?

Beitrag von GPI »

Die Antwort ist simple - das ist nicht die Aufgabe des Compilers!

Wenn man mit @ die Adresse einer Funktion sich hohlt, verliert man alle Informationen über Rückgabewerte, parameter etc. Dafür sind doch die Prototypen da, damit der Compiler wieder diese Informationen bekommt. Wenn man hier blödsinn macht, dann kann der Compiler nichts dafür.

Code: Alles auswählen

 Prototype.f ReturnF(*Pointer)

Global var.ReturnF

Procedure.i proc(x,y,z)
   ProcedureReturn x*y*z
EndProcedure


Procedure.i xyz()
    ProcedureReturn var(1)
EndProcedure


*var2 = @proc()
var = *var2


Debug xyz()
zur verdeutlichung. Die Adresse könnte ja auch aus einer dll kommen - da hat man auch nichts.

Der compiler reagiert absolut korrekt.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Prototype - gefahren bei Typenkollision?

Beitrag von Danilo »

GPI hat geschrieben:Die Antwort ist simple - das ist nicht die Aufgabe des Compilers!
Wo hast Du denn Compilerbau studiert?

Natürlich ist es die Aufgabe des Compilers Typüberprüfungen durchzuführen!

Das kannst Du nicht überhört oder überlesen haben, denn das ist eines
der zentralen Themen beim Compilerbaustudium.
GPI hat geschrieben:Wenn man mit @ die Adresse einer Funktion sich hohlt, verliert man alle Informationen über Rückgabewerte, parameter etc.
Wer ist "man"? Ich rede von Compilern.

Der Compiler hat in dem Beispiel lhs, rhs und alle benötigten Typinformationen:
lhs = var
rhs = @proc()

typeof var = Prototype.f ReturnF(*Pointer)
typeof @proc() = adressOf Procedure.i proc(x,y,z)

Und weil der Compiler diese Informationen hat, muß er prüfen ob rhs mit lhs
Typkompatibel ist. Das ist hier nicht der Fall, also muß der Compiler eine
entsprechende Fehlermeldung ausgeben.
GPI hat geschrieben:zur verdeutlichung. Die Adresse könnte ja auch aus einer dll kommen - da hat man auch nichts.

Der compiler reagiert absolut korrekt.
Wenn der Pointer aus einer DLL kommt, dann muß diese Funktion eben auch
den gleichen Typ haben. Das heißt in diesem Beispiel, die DLL-Funktion gibt
einen Pointer vom Typ 'ReturnF' zurück, was ein Verweis auf den korrekten
Prototype ist.
GetFunction() beispielsweise gibt einen unbekannten Pointer zurück, also
muß der Programmierer hier willentlich eine Typkonvertierung (casting)
durchführen, z.B. nach 'ReturnF'. Macht er dies nicht, muß ein Fehler kommen.

Das ist die zentrale Aufgabe von Compilern. Was Du meinst sind simple Übersetzer,
die von A nach B übersetzen und keine Semantiküberprüfung durchführen.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7039
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Prototype - gefahren bei Typenkollision?

Beitrag von STARGÅTE »

Um zum Thema zurück zu kommen:
Es gibt also keine möglichkeit "einfach nur" eine Prozedur aufzurufen, weil diese immer mit einem Rückgabewert verknüft sein muss?

Das heißt, wenn dann muss ich erst eine zwischen Prozedur aufrufen, die nur die Aufgabe hat, dann den richtigen Prototyp zuverwenden.
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
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Prototype - gefahren bei Typenkollision?

Beitrag von GPI »

@ Danilo

in der theorie schon, nur so funktioniert das bei purebasic nicht.
bsp:

*var2=@proc()
var =*var2

ist gültig und funktionstüchtig. *var2 hat hier keinen Typ. Die Info gehen verloren.

Gultig ist auch

var2.i=@proc()
var=var2

var ist hier ein prototyp.

Eine Änderung würde viele codes ungültig machen. Ein compiler sollte hier auch eher warnen und nicht verhindern.

@topic
jede funktion gibt einen Wert zurück. wenn du nichts angibst, wird in der Regel eine Null zurückgegeben - darauf würde ich mich aber nicht verlassen!
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Prototype - gefahren bei Typenkollision?

Beitrag von Danilo »

GPI hat geschrieben:in der theorie schon, nur so funktioniert das bei purebasic nicht.
Ich weiß das es bei Purebasic nicht so funktioniert. Das ist ja genau das große Problem. :)

Wenn Du schonmal mit C, C++, C# oder Java programmiert hast, weißt Du um was
es bei der Typsicherheit geht.
Da hätte STARGÅTE eine entsprechende Fehlermeldung bekommen und wüßte wo
das Problem liegt.

PB ist halt so, es gibt keine Warnung oder Fehlermeldung bei solchen Fehlern aus.
Würde PB das tun, wäre es viel mehr zu gebrauchen und würde den Programmierer
unterstützen, statt ihm das Leben schwer zu machen. Zum Beispiel bei der Fehlersuche,
weil es Konstrukte zulässt, die nicht sein dürfen.

Aber egal, interessiert hier eh keinen und ändert sich auch nichts... :D
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
CSHW89
Beiträge: 489
Registriert: 14.12.2008 12:22

Re: Prototype - gefahren bei Typenkollision?

Beitrag von CSHW89 »

@Danilo:
Ein Typensystem ist nicht das Maß aller Dinge. Es gibt genügend Programmiersprachen, die kein, bzw. ein dynamisches Typensystem haben, bei denen es häufig erst zur Laufzeit Typenfehler erkennt, wie z.B. LISP, oder auch modernere Sprachen, wie Ruby, die durchaus angesehen sind, bzw. ihre Darseinsberechtigung haben.
Versteh mich nicht falsch, auch ich schätze ein gutes Typensystem. Hab auch Compilerbau gehört, bzw. mache gerade ein Software-Praktikum. Aber wenn die Sprache halt nicht danach ausgelegt ist, dann ist das so. PureBasic hat nunmal die Entscheidung getroffen, dass Pointer immer zuweisungsberechtigt sind. Ist doch das gleiche Thema mit OOP. Die die sowas wollen, sollten andere Sprachen verwenden.
Du must auch bedenken: das jetzt zu ändern, wäre einfach fatal. 99% aller Codes wäre einfach nicht mehr lauffähig. Das wäre so, als wenn wir jetzt sagen würden, auf Strukturelemente greift man nicht mehr mit '\', sondern mit '.' zu.

lg kevin
Bild Bild Bild
http://www.jasik.de - Windows Hilfe Seite
padawan hat geschrieben:Ich liebe diese von hinten über die Brust ins Auge Lösungen
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Prototype - gefahren bei Typenkollision?

Beitrag von Nino »

STARGÅTE hat geschrieben:Es gibt also keine möglichkeit "einfach nur" eine Prozedur aufzurufen, weil diese immer mit einem Rückgabewert verknüft sein muss?
Nicht mit einem Rückgabewert, aber mit einem bestimmten Rückgabetyp.

Es gibt andere Programmiersprachen, bei denen man ziemlich allgemeine Funktionen definieren kann, deren Rückgabetyp nicht festgelegt ist. Pseudocode:

Code: Alles auswählen

function demo(p)
   if p = 1 then
      return -27
   elseif p = 2 then
      return 4.3
   else
      return "Hallo"
   end if
end function
Es wird also dynamisch zu Laufzeit entschieden, ob z.B. ein Integer, ein Float oder ein String zurückgegeben wird.

Bei PB geht das nicht, denn in dem Moment, wo Du schreibst

Code: Alles auswählen

Procedure.i
Procedure.s
Procedure.f
usw.
ist der Rückgabetyp in PB fesgelegt.

Eine Prozedur die einen Pointer zurückgibt, muss als Procedure.i definiert sein. Was aber an der Stelle im Speicher steht, auf die der Pointer zeigt, kann von Dir dynamisch zur Laufzeit bestimmt werden (z.B. eine strukturierte Variable). :)

Grüße, Nino
Antworten