Bugs und vermeintliche | | | | - Seite 1 - |
| Dieter Zornow | Ich denke es ist noch ein Problem in XProfan 11, habe gerade auch nochmals die OCX - Beispiele von Uwe Pascal N. getestet. Unter XProfan 10 läuft alles noch einwandfrei. Unter XProfan 11 RC 8 nur Abstürze bei jedem Beispiel.
Gruss
Dieter |
| | | Er ist ein Mann wie ein Baum. Sie nennen ihn Bonsai., Win 7 32 bit und Win 7 64 bit, mit XProfan X2 | 29.06.2008 ▲ |
| |
| | | | | - Seite 1 - |
| | Nutzt Delphi da Heaps [...] ? |
| | | | |
| | RGH | ... und so wie es aussieht, laufen auf meinem Rechner zu Hause (XP Pro SP3) die Beispiele von Uwe Pascal werder unter XProfan 10 noch unter XProfan 11. Es kommt immer die Meldung CallMethod - Unbekannter Name. (Ja, ich habe die ComCtl32.ocx registriert ....) In der Firma (XP Pro SP2 hat es geklappt.)
Dann muß ich mich wohl doch anderen Themen zuwenden ...
Gruß 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 | 30.06.2008 ▲ |
| |
| | Uwe ''Pascal'' Niemeier | Hallo Leute!
Zunächst mal: Ich habe im Moment weder XP SP3 noch XProfan 11 zur Verfügung, darum kann ichs nicht selbst testen.
Aber: Die von Roland reklamierten Variablen haben in dieser Version der OCX-Routinen direkt nichts mit den ActiveX-Funktionen zu tun: KompilierenMarkierenSeparieren
proc ocxCreate----------------------------------ocxCreate-------------------------------
parameters ProgID$,Wnd&,xa%,ya%,xb%,yb%,ObjAddr&,CtrlAddr&
declare Control&,IUnknown&,Object&
Control&=control(AtlAxWin,ProgID$,$50000000,xa%,ya%,xb%,yb%,Wnd&,0,0,0)
~AtlAxGetControl(Control&,addr(IUnknown&))
Object&=QueryInterface(IUnknown&,~IID_IDispatch)
CallMethod(IUnknown&,~Release)
long ObjAddr&,0=Object&
long CtrlAddr&,0=Control&
endproc---------------------------------------------------------------------------------
declare Object&,Control&
ocxCreate(MSCAL.Calendar.7,%hwnd,10,100,350,250,addr(Object&),addr(Control&))
Die beiden Pointer kommen in der Proc als ObjAddr& und CtrlAddr& an, Object& und Control& werden lokal nochmal deklariert und am Ende der Proc werden die - als Parameter übergebenen - Pointer mit LONG gefüllt.
Das Problem könnte also auch in der direkten Übergabe von addr(Variable&) als Parameter für eine Prozedur liegen oder in der lokalen Deklaration einer global bereits vorhandenen Variable...
PS: Im Beispiel wird Version 1 der OCX-Routinen verwendet. Wie sieht es denn mit Version 2 aus?
SeeYou Pascal |
| | | | |
| | | | - Seite 2 - |
| | RGH | Hallo,
ich habe mir die Sache gestern Abend noch mal genauer angeschaut. Es ist auch weiterhin so, dass eine Variable während ihrer Gültigkeit Ihre Adresse nicht ändert. Von daher also eine Entwarnung!
Das Problem liegt in Pascals Create-Routine, bzw. der Übergabe der Variablen aus dieser zurück: KompilierenMarkierenSeparieren
Proc ocxCreate----------------------------------ocxCreate-------------------------------
parameters ProgID$,Wnd&,xa%,ya%,xb%,yb%,ObjAddr&,CtrlAddr&
declare Control&,IUnknown&,Object&
Control&=control(AtlAxWin,ProgID$,$50000000,xa%,ya%,xb%,yb%,Wnd&,0,0,0)
~AtlAxGetControl(Control&,addr(IUnknown&))
Object&=QueryInterface(IUnknown&,~IID_IDispatch)
CallMethod(IUnknown&,~Release)
long ObjAddr&,0=Object&
long CtrlAddr&,0=Control&
endproc---------------------------------------------------------------------------------
Über PARAMETERS werden die beiden Adressen in den lokalen Variablen ObjAddr& und CtrlAddr& gespeichert. Deren Adressen werden aber mit Verlassen der Prozedur ungültig. In XProfan 11 haben Object& und Control& den Wert 0 ... was dann unweigerlich zum Crash führt. Möchte man mehrere Werte aus einer Prozedur zurückerhalten wempfiehlt sich immer der Weg über eine struktur oder über ein Objekt, da - wie in nahezu allen Sprachen - Strukturen und Objekte per Adresse übergeben werden. So sieht die angepaßte Create-Prozedur aus: KompilierenMarkierenSeparieren
proc ocxCreate----------------------------------ocxCreate-------------------------------
parameters ProgID$,Wnd&,xa%,ya%,xb%,yb%,Uebergabe#
declare IUnknown&
Uebergabe#.Control&=control(AtlAxWin,ProgID$,$50000000,xa%,ya%,xb%,yb%,Wnd&,0,0,0)
~AtlAxGetControl(Uebergabe#.Control&,Addr(IUnknown&))
Uebergabe#.Object&=QueryInterface(IUnknown&,~IID_IDispatch)
CallMethod(IUnknown&,~Release)
endproc---------------------------------------------------------------------------------
Auch die Prozedur QueryInterface() muß entsprechend angepaßt werden (Aufruf von CallMethod()): KompilierenMarkierenSeparieren
proc QueryInterface-------------------------------------------------------------
parameters IFace1&,IID$
declare IFace2#,Error&
dim IFace2#,4
StringToGUID(IID$,IID#)
Error&=CallMethod(IFace1&,0,IID#,IFace2#)
case Error&<0:ErrorMessage(Error&,QueryInterface)
CallMethod(IFace1&,~Release)
return long(IFace2#, 0)
endproc-----------------------------------------------------------------------
Und so nun das Beispielprogramm: KompilierenMarkierenSeparierenwindow 100,10-500,500
usermessages 16
$H Windows.ph
$H OCX.ph
$I OCX.inc
Nur zur Demo. Normalerweise würde man die Übergabestruktur in OCX.ph definieren
Struct SUebergabe = Object&, Control&
declare U#
dim U#, SUebergabe
declare ATL&,Var#,Disp#,IID#
ocxInit()
ocxCreate(MSCAL.Calendar.7,%hwnd,10,100,350,250,U#)
ocxMethod(U#.Object&,Today)
numwidth 3
while 1
locate 0,0
print Tag ,ocxGet(U#.Object&,Day)
print Monat ,ocxGet(U#.Object&,Month)
print Jahr ,ocxGet(U#.Object&,Year)
waitinput
case %umessage=16:break
endwhile
ocxMethod(U#.Object&,AboutBox)
destroywindow(U#.Control&)
ocxDeInit()
Gruß 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 | 01.07.2008 ▲ |
| |
| | RGH | Noch kurz zur Erklärung für Insider:
In Xrofan 11 werden tatsächlich mit Verlassen einer Prozedur die Adressen der lokalen Variablen wieder ungültig und der entsprechende Speicher wird wieder frei gegeben.
Bis einschließlich XProfan 10 wurde der Speicher für alle möglichen Variablen ja beim Start zur Verfügung gestellt.* Beim Verlassen der Prozedur wurde zwar der Zeiger auf die letzte Variable zurückgesetzt, so dass auf die lokalen Variablen der Prozedur nicht mehr zugegriffen werden konnte und der Speicher für die Deklaration neuer Variablen wieder zur Verfügung stand, aber der Speicher wurde nicht freigegeben. Und so lange dieser nicht durch neue Declares genutzt wurde, blieben die alten Werte dort stehen.
Gruß Roland
* Bei Strings, Arrays und Bereichen allerdings nur die Zeiger auf den Speicher ... aber das wäre jetzt ein anderes Thema ... |
| | | 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 | 01.07.2008 ▲ |
| |
| | Sebastian König | RGH
Über PARAMETERS werden die beiden Adressen in den lokalen Variablen ObjAddr& und CtrlAddr& gespeichert. Deren Adressen werden aber mit Verlassen der Prozedur ungültig. In XProfan 11 haben Object& und Control& den Wert 0 ... was dann unweigerlich zum Crash führt.
Das Argument verstehe ich irgendwie nicht... in den Parametern ObjAddr& und CtrlAddr& werden doch die Adressen von globalen Variablen übergeben (siehe Pascals Code oben). Was genau ist dann das Problem bei einer Zuweisung der Form long ObjAddr&,0=Object&? Worauf genau ObjAddr& nun zeigt, macht aus Sicht der Prozedur ja keinen Unterschied und dass Object& nun eine lokale Variable ist, dürfte auch keine Rolle spielen.
So wie ich die Beschreibung verstehe, ist das ganze doch äquivalent zu einem solchen Beispiel: KompilierenMarkierenSeparieren Und der Code funktioniert bei mir mit XProfan 10 und 11 gleichermaßen problemlos...
MfG
Sebastian |
| | | | |
| | RGH | Ja, rOlf, ich vermute Du hast recht: Meine Erklärung war etwas zu kurz gegriffen. Tatsache ist, dass die entsprechend veränderten und von mir geposteten Quellcodes auch unter XProfan 11 einwandfrei funktionieren. (Zumindest hier am Arbeitsplatz-PC. Zuhause auf meinem Rechner klappt gar nichts mit ActiveX - weder in XProfan 10 noch 11. Ich muß mal überprüfen, ob meine ComCtl32.ocx die richtige ist.)
Möglicherweise hängt das Problem auch damit zusammen, dass lokale Variablen an ActiveX-Funktionen gegeben werden, die auch nach dem Verlassen der Prozedur noch aktiv sind und so plötzlich auf nicht mehr gültige Adressen zugreifen. Ich werde bei Gelegenheit weiterforschen. Wichtig ist hier, dass wir eine Lösung für das Problem haben und Uwe Pascals Quellcodes auch für XProfan11-Nutzer offen stehen.
Gruß 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 | 01.07.2008 ▲ |
| |
| | Frank Abbing | Wenn das Problem nur lokale Variablen betrifft und nicht die Globalen, kann ich damit durchaus leben. Dass lokale Variablen bei erneutem Aufruf einer Prozedure gelöscht werden, ist ja durchaus gängige Praxis. So bin ich es auch von Assembler aus gewohnt. |
| | | | |
| | Uwe ''Pascal'' Niemeier | Hallo Leute!
Möglicherweise hängt das Problem auch damit zusammen, dass lokale Variablen an ActiveX-Funktionen gegeben werden, die auch nach dem Verlassen der Prozedur noch aktiv sind und so plötzlich auf nicht mehr gültige Adressen zugreifen.
Das könnte aber nur auf IUnknown& zutreffen, was aber anscheinend nicht der Fall ist. Die Werte für/von Control& und Object& (lokal) werden direkt zugewiesen ; es werden keine Pointer verwendet. Folglich kann auch kein späterer Zugriff darauf erfolgen. Wegen QueryInterface() muß ich mal schauen...
Wichtig ist hier, dass wir eine Lösung für das Problem haben und Uwe Pascals Quellcodes auch für XProfan11-Nutzer offen stehen.
Mir ging es ja auch darum, die Routinen möglichst weit abwärtskompatibel zu halten, darum habe ich auf OOP verzichtet. Ist aber schon für OCX-Package Version 3 vorgemerkt. Wäre aber trotzdem gut, dieses Problem bis dahin geklärt zu haben. Die Übergabe von Pointern, um Variablen zu füllen sollte ja - trotz OOP - durchaus nicht ungewöhnlich sein.
PS: Die Schwierigkeiten mit SP3 werde ich mir demnächst vornehmen.
SeeYou Pascal |
| | | | |
| | RGH | Hallo Pascal,
die Übergabe von Pointern, um Variablen zu füllen, ist - wie Rolf ja auch schon festgestellt hat - nicht das eigentliche Problem. Das Problem vermute ich eben in dem Bereich, wo Adressen lokaler Variablen an Funktionen übergeben werden, die auch nach Beendigung der aufrufenden Prozedur (und dem Ungültigwerden eben dieser Adressen) noch weiterlaufen. Hierzu zählen offensichtlich ActiveX-Objekte. Auf Anhieb kann ich in Deinem Code zwar keine derartigen Aufrufe mit Adressen lokaler Variablen erkennen, aber ActiveX hat da möglicherweise Eigenheiten, die mir noch nicht geläufig sind. Da ich momentan auf meinem Entwicklungsrechner die Beispiele nicht mal unter XProfan 10 zum Laufen bekomme, muß ich eine weitere Analyse auf die Zeit nach dem Release von XProfan 11 verschieben. (Da werde ich meinem Rechner ein neues Motherboard mit besserem Prozessor gönnen. Vor dem Release gilt ganz streng: Never Change A Running System.) Und sollte ich wirklich dann feststellen, dass ich in XProfan was tun kann, spricht ja nichts gegen ein kostenloses Update auf ein XProfan 11.0a oder gar 11.1.
Wenn es keine wirklichen ShowStopper mehr gibt, wird XProfan 11 demnächst festgeklopft und endlich an JDS geliefert. Ich bin eh schon (teils durch berufliche und private Auslastung, teils durch Maßlosigkeit beim Einbau neuer Features) etwa 2 Monate hinter meinem ursprünglichen Zeitplan.
Gruß 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 | 02.07.2008 ▲ |
| |
| | RGH | Hallo Pascal, ich habe es nicht lassen können und meine Frühstückspause am Arbeitsplatzrechner geopfert:
Der oben gepostete Code scheint nicht 100%ig stabil zu sein. Wenn ich das Declare in der Prozedur CallMethod um mehr als drei Variablen erweitere, bricht das Programm mit einer Fehlermerldung ab. Sehr befremdlich, das! Also habe ich etwas weiter experimerntiert.
Es xcheint tatsächlich mit dem QueryInterface zusammenzuhängen. Ich habe mal geschaut, was ich in XProfan beim HTML-Window anders mache: Da ich ja nur das Control zurückgebe, mache ich jedesmal ein neues QueryInterface, um die Objektadresse zu ermitteln (und natürlich nach Gebrauch des Objektes ein Releasen). Das habe ich mal in Deinem OCX.INC umgesetzt. Zunächst ein ocxCreateC() (das C steht für Control): KompilierenMarkierenSeparieren
proc ocxCreateC ----------------------------------ocxCreate-------------------------------
parameters ProgID$,Wnd&,xa%,ya%,xb%,yb%
return control(AtlAxWin,ProgID$,$50000000,xa%,ya%,xb%,yb%,Wnd&,0,0,0)
endproc ---------------------------------------------------------------------------------
Dann die Proceduren ocxGet, ocxPut und ocxMethod als ocGetC, ocxPutC und ocxMethodC kopiert und entsprechend erweitert. Als Beispiel hier ocxGetC(): KompilierenMarkierenSeparieren
proc ocxGetC-------------------------------------ocxGet----------------------------------
parameters Control&,Name$
declare Object&,IUnknown&
declare DispID&,v&,v$
~AtlAxGetControl(Control&,addr(IUnknown&))
Object&=QueryInterface(IUnknown&,~IID_IDispatch)
clear Var#,Disp#,IID#
Name$=MultiToWideEx(Name$)
v&=addr(Name$)--GetIDsOfNames braucht Pointer auf Pointer
CallMethod(Object&,5,IID#,addr(v&),1,0,addr(DispID&))--GetIDsOfNames
CallMethod(Object&,6,DispID&,IID#,0,~DISPATCH_PROPERTYGET,Disp#,Var#,0,0)--Invoke
if Var#.vt%=~VT_BSTR------OLE-String
v$=WideToMultiEx(Var#.Val&)
else----------------------numerischer Wert
v$=str$(Var#.Val&)
endif
~VariantClear(Var#)
CallMethod(IUnknown&,~Release)
return v$
endproc---------------------------------------------------------------------------------
ocxQueryInterface habe ich so gelassen, wie oben gepostet (mit IFace2#). Und schon klappt alles (zumindest hier am Arbeitsplatz ;) )
Nur ne vage Theorie, oder besser Hypothese: Vermutlich kann sich das ActiveX-Objekt im Speicher verschieben, was aber bei der statischen Speicherverwaltung in XProfan 10 bei den Beispielprogrammen nicht vorkam, da da ja nirgendwo neuer Speicher angefordert wurde. Jetzt ermittle ich über QueryInterface die Objektadresse (Object&) jedesmal neu und das Problem scheint behoben.
Gruß 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 | 02.07.2008 ▲ |
| |
| | Uwe ''Pascal'' Niemeier | Hallo Roland!
Nur ne vage Theorie, oder besser Hypothese: Vermutlich kann sich das ActiveX-Objekt im Speicher verschieben, was aber bei der statischen Speicherverwaltung in XProfan 10 bei den Beispielprogrammen nicht vorkam, da da ja nirgendwo neuer Speicher angefordert wurde.
Klingt gewagt... Bei der Entwicklung der OCX-Routinen habe ich keine Hinweise auf so ein Verhalten gefunden. Allerdings wird bei Programmiersprachen mit ActiveX-Unterstützung ja so ziemlich alles als selbstverständlich vorausgesetzt (was die Umsetzung nach Profan ja so schwer macht). Möglicherweise werden da die Pointer automatisch nachgeführt oder so.
Werde mich nochmal dahinterklemmen, wenn es an der Zeit ist.
Wenn es keine wirklichen ShowStopper mehr gibt, wird XProfan 11 demnächst festgeklopft und endlich an JDS geliefert.
Hat auf jeden Fall Priorität! Falls das bis Oktober klappt, hol ichs mir persönlich bei JDS ab (Im Herbst zelten an der See ist was feines )
Und einen Workaround haben wir ja nun auch
Danke für die Mühe!
SeeYou Pascal |
| | | | |
|
AntwortenThemenoptionen | 9.145 Betrachtungen |
ThemeninformationenDieses Thema hat 6 Teilnehmer: |