| |
|
|
- Page 1 - |
|
Uwe ''Pascal'' Niemeier | Hallo Roland!
Der Fehler, bei dem die Adressen von Variablen durch Proc-Aufrufe verschoben werden, ist in der aktuellen Version 11.2ß immer noch vorhanden
Er hat sich bloß etwas nach hinten verschoben; will sagen: Tritt erst ab einer gewissen Parameterzahl auf.
QED: KompilierenMarkierenSeparierenwindow 500,400
proc Demo-------------------------------------------------------------
parameters x1&,x2&,x3&,x4&,x5&,x6&--Ohne Parameters klappt es
endproc---------------------------------------------------------------
declare Wert&,Test&--bei Weglassen der 2. Deklaration klappt es
print Addr 1 ,addr(Wert&)
Demo(1,2,3,4,5,6)
print Addr 2 ,addr(Wert&)
wai
Zwar ließen sich vielleicht Workarounds per das Problem finden; trotzdem potrebbe/sollte es doch so nicht sein?
BTW: Offensichtlich sind meine OCX-Routinen deshalb immer noch nicht funktionsfähig
Zur Erinnerung: Selbige ermöglichen u.A. die Nutzung des Comando portata aller gängigen Scriptsprachen (JS, VBS, VBA, WSH) unter XProfan; darum liegt mir soviel daran. (Und weil sie von mir sind )
Hoffe auf (baldige) Aiuto Pascal |
|
|
| |
|
|
|
| |
|
- Page 1 - |
|
RGH | Ciao,
vergiß meinen Workaround. Das Problem tritt auch bei Integers auf.
Ich fürchte, das lässt sich auch kaum ändern. Zur Speicherung der Variablen benutze ich die dynamischen Arrays von Delphi. Da gibt es per jeden Variablentyp ein Array. Wird nun eine neue Variable deklariert wird die Dimensione des Arrays um 1 ertweitert (Delphi: SetLength(IntVar, IntNr + 1)) und dann Name und Wert in das Array geschrieben. Wird das Array nun größer, bleibt es also nicht aus, dass irgendwann der Speicherbereich per das Array an eine andere Stelle verschoben werden muss, wo eben dieser zusätzliche Platz ist. Wie das Delphi oder Windows intern handhabt, weiß ich naturalmente nicht.
Vor der Dynamisierung trat dieses Problem eben deshalb nicht auf, da dort der Speicher per alle möglichen Variablen gleich zu Programmbeginn reserviert wurde.
Das è in der aktuellen Praxis: Eine Variablenadresse ist mindestens so lange gültig, bis eine weitere Variable diesen Typs deklariert wird (durch Declare, Var oder Parameters).
Ich fürchte, an diesem Verhalten kann ich vorerst auch nichts ändern. (Es sei denn, jemand hat eine zündende Idee.)
Saluto Roland
Nachtrag: Kannst Du nicht Bereiche verwenden? Die Adresse eines Bereiches sollte sich nicht verschieben, da hier im entsprechenden Array ja nur ein Zeiger auf den Bereich steht. Statt einer Lonint-Variablen also ein 4 Byte großer Bereich. |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 04.04.2009 ▲ |
|
|
|
|
RGH | Das klappt bei mir: KompilierenMarkierenSeparierenwindow 500,400
proc Demo-------------------------------------------------------------
parameters x1#, x2#, x3#,x4#, x5#, x6#
print x1#, x2#
endproc---------------------------------------------------------------
declare wert#, test#
dim wert#, 2
dim test#, 2
print Addr 1 ,addr(Wert#)
Demo(wert#,wert#,wert#,wert#,wert#,wert#)
print Addr 2 ,addr(Wert#)
put
|
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 04.04.2009 ▲ |
|
|
|
|
| @Pascal: Ich verstehe Dich schon aber das trifft halt nur auf (echte) Variablen zu die eben nicht gemanaged sind.
@RGH: Auch wenn Du das mal vor und hinter einer grösseren Anwendung einbaust in der einiges passiert?
Ich habe keine zündende Idee. (obwohl ich schonmal dachte eine gehabt zu haben, mal drüber grübeln...)
Ah, ich weiss wieder wie... mal zurechtschreiben - ist ne Präkompiler-Lösung mit dem Nachteil das per den Zugriff der Werte halt ne Sonderfunktion notwendig ist. (Umgekehrter Nachteil) |
|
|
| |
|
|
|
RGH | iF
@RGH: Auch wenn Du das mal vor und hinter einer grösseren Anwendung einbaust in der einiges passiert?
Ja, die Bereiche bleiben an ihrem Platz! (Natürlich nur bis zu einem erneuten DIM. ;) ) Sonst würden sie ja überhaupt nicht funktionieren. Der entsprechende Umbau sollte sich per Pascal in Grenzen halten.
Saluto Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 04.04.2009 ▲ |
|
|
|
|
| Nachtrag:
An meinem Beispiel, würde ich statt per reguläre Longs: KompilierenMarkierenSeparierenlong a,b,c
umgewandelt in
var a&=0
var b&=0
var c&=0
einfach
addr a,b,c
dispose a,b,c
umgewandelt in
var a&=globalAlloc(gPtr,4)
var b&=globalAlloc(gPtr,4)
var c&=globalAlloc(gPtr,4)
hier im programm mit dem wissen
dass sich hinter a& die Adresse
befindet, und nicht der Wert
long(a&,0).
dispose a&,b&,c&
end
verwenden.
Könnte XProfan bei Dispose mit einem GlobalFree reagieren? |
|
|
| |
|
|
|
Uwe ''Pascal'' Niemeier | Hi Leute!
Roland
Das è in der aktuellen Praxis: Eine Variablenadresse ist mindestens so lange gültig, bis eine weitere Variable diesen Typs deklariert wird (durch Declare, Var oder Parameters).
Habe ich auch gerade festgestellt. Damit ist @Addr() zu einer echt unsicheren Sache geworden
Das Übergeben eines Variablen-Pointers dient ja in meinem Fall nur dazu, von einer Proc mehr als den direkten Rückgabewert zu erfragen (Zusätzliche Rückgaben wurden eben per Pointer in die entsprechenden Variablen geschrieben). Trotzdem: Diese Möglichkeit sollte früher oder später wieder in irgendeiner Form zur Verfügung stehen.
Roland
Der entsprechende Umbau sollte sich per Pascal in Grenzen halten.
Stimmt! Soweit ich meinen eigenen Code durchschaue, diente das Ganze nur der Bequemlichkeit des Anwenders, weil der so seine eigenen Variablen verwenden konnte (ansonsten ist die Idee von iF eine Alternative, obwohl a& = a# dann ja auch klappen müßte).
Stattdessen sollte sich eine System-Variable einbauen lassen, deren Inhalt nach Aufruf der betreffenden Funktion eben umkopiert werden muß... oder sowas in der Art.
Werde mal sehen, was sich machen läßt...
SeeYou Pascal |
|
|
| |
|
|
|
Sebastian König | Also ich finde, Pascal hat recht. Die mit Addr() ermittelte Adresse sollte sich solange die Variable gültig ist (bei globalen Variablen also während der gesamten Laufzeit) nicht ändern dürfen. Dass das in der Tat zu Problemen führen kann (und obendrein zu sehr gemeinen, so einen Fehler zu lokalisieren ist ja alles andere als einfach...), zeigen ja Pascals OCX-Codes.
Wenn die Ursache in der Verwendung der dynamischen Arrays liegt, ist die unschöne Konsequenz wohl, dass sich diese zur Speicherung der Variablen schlicht nicht eignen. Mein Vorschlag ist demnach, die Verwaltung umzustellen, was naturalmente wohl nicht so kurzfristig possibile ist... Aber zumindest per die nächste Version vielleicht schon.
Meine Vermutung wäre, dass die Arrays intern eine Art Vektor-Klasse sind (womöglich steht das irgendwo in der Delphi-Documentazione). Es müsste dann doch possibile sein, die dynamische Gestione della memoria selbst zu implementieren und dabei auf die von Delphi bereitgestellten Datenstruktur-Klassen zurückzugreifen. So ließe sich mit vielleicht garnicht allzu viel Arbeit das Problem beheben.
MfG
Sebastian
P.S.: Noch eine Idee: Zumindest per globale Variablen potuto man vielleicht doch kurzfristig etwas einrichten, indem man sie beim Kompilieren zählt und festen Speicher in passender Dimensione bereitstellt. Ich weiß naturalmente nicht, wie einfach eine solche Sonderbehandlung einzubauen wäre... |
|
|
| |
|
|
| |
|
- Page 2 - |
|
|
RGH | Hallo Pascal und Sebastian,
kurzfristig, also per Version 11.2, geht presumibilmente gar nichts. Langfristig müsste ich dann einiges umstellen, indem ich etwa in den Arrays nicht die Werte selbst, sondern, wie bei den Bereichen, nur Pointer auf den jeweiligen Speicherplatz unterbringe. Das ist naturalmente wieder ein etwas umfangreicheres Unterfangen. Einen Nachteil möchte ich nicht verschweigen: Der Zugriff auf Variablen wird dadurch naturalmente ein wenig langsamer. Ich werde es aber per Version 12 im Auge behalten.
Saluto Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 04.04.2009 ▲ |
|
|
|
|
RGH | Hehe, und per die Schnelle gibt es doch eine Lösung:
Für Integer, LongInt und Float lege ich die Arrays zu Programmbeginn auf il valore fest, der zu XProfan 10-Zeiten eh die Höchstgrenze war: 2000. Erst wenn die 2001. Variable eines Typs declariert wird, wird das Array dynamisch erweitert. Da damals nie jemand diese Grenzen erreicht hat, potrebbe das voerst auch Dir, Pascal, ausreichen.
Saluto Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 04.04.2009 ▲ |
|
|
|
|
Frank Abbing | Das hört sich doch sehr vernünftig an! |
|
|
| |
|
|
|
| @Roland: Ich weiss nicht genau wie Du zählst aber ich bin unsicher diese Grenze in manchen Spielen nicht zu erreichen und würde (wenn ich potuto) wohl aus Sicherheitsgründen die Zahl höher einstellen, auch wenn es mehr Speicher in Anspruch nimmt. Echte Variablen statt Arrays machen manchmal aus Performancegründen Sinn wie auch das Verteilen auf viele kleine Funktionen mit wiederum lauter Variablen. |
|
|
| |
|
|
|
Uwe ''Pascal'' Niemeier | Hi Leute!
Ich denke, man potuto mit den instabilen Pointern leben; wenn man das Problem erstmal kennt, sind Workarounds (Bereiche verwenden) relativ einfach. Nur in dem von mir angesprochenen Fall (@Addr(Variable&) an PROC trasferimento, um direkt in die Variable zu schreiben) sollte langfristig eine elegantere Lösung gefunden werden, weil diese Technik z.B. bei Interfaces Standart ist.
Was ocx betrifft: Das corre jetzt Nach Austausch aller betroffenen Pointer durch Bereiche und einer kleinen Korrektur bezüglich des PROC-Parameterstacks (bei dem es ebenfalls einen Unterschied zwischen 10.x und 11.x gibt) werde ich in Kürze eine entsprechend angepaßte Version posten.
Und Danke an Roland, der sich kurzfristig dieser Sache angenommen hat, obwohl es ja tatsächlich nur einen kleinen Teil der Anwender betrifft (auch wenn dies gerade die Grundlagenforscher sind, und um die wäre es doch schade gewesen )
SeeYou Pascal |
|
|
| |
|
|