Seite 2 von 2
Re: Private / Public / Threads / Errorsys
Verfasst: Fr, 10. Dez 2010 12:33
von brandelh
ich meine, dass MEMVAR keine erzeugt, sondern lediglich M-> unnötig macht (sollte man dennoch ausprobieren !)
Somit müsste eine BESTEHENDE PRIVATE von übergeordneten Programmen weiterhin genutzt werden.
Wenn es die aber nicht gibt, dann wird eine neue zur Laufzeit erzeugt.
Re: Private / Public / Threads / Errorsys
Verfasst: Fr, 10. Dez 2010 12:41
von Tom
SymbolInfo() sollte helfen, um herauszufinden, welche Art von Variable es ist. Jedenfalls definiert man PUBLICs über die PUBLIC-Anweisung. Sie existieren in diesem Moment allerdings noch nicht, sondern erst im Moment der Wertzuweisung. Wenn man das wiederholt, sollte man sofort wieder einen Wert zuweisen, sonst ist die Variable auch nicht definiert. Also PUBLIC cMyPath := '' oder ähnlich.
Re: Private / Public / Threads / Errorsys
Verfasst: Fr, 10. Dez 2010 12:52
von Christian
Hallöchen,
wie Manfred schon andeutete kann eine Klasse hier wirklich Abhilfe schaffen können.
Es sollten einfach nur alle Klassenvariablen als CLASS VAR deklariert werden.
Code: Alles auswählen
CLASS PublicVar
EXPORTED:
METHOD initClass
VAR zPath
ENDCLASS
METHOD PublicVar:initClass()
// Aufruf dieser Methodde erfolgt automatisch beim erstmaligen Aufruf des Klassenobjekts
// hier können ggf. default-Werte für alle Variablen angegeben werden
zPath := ""
RETURN self
Von außen kann die Variable über das Klassenobjekt abgefrag oder gesetzt werden:
Es ist also keine Klasseninstanzierung mehr notwendig und voll multi-threading-kompatibel.
mfg
Christian
Re: Private / Public / Threads / Errorsys
Verfasst: Fr, 10. Dez 2010 13:10
von brandelh
Tom hat geschrieben:Jedenfalls definiert man PUBLICs über die PUBLIC-Anweisung. Sie existieren in diesem Moment allerdings noch nicht, sondern erst im Moment der Wertzuweisung.
da bin ich auch anderer Meinung, zur Laufzeit wird das Programm, sobald es an diese Stelle kommt, eine PUBLIC erzeugen und diese mit NIL belegen !
Ab diesem Moment existiert die Variable und Valtype() gibt keine Fehlermeldung.
Re: Private / Public / Threads / Errorsys
Verfasst: Sa, 11. Dez 2010 6:41
von AUGE_OHR
hi,
ich bin mir gar nicht mehr sicher ob ich immer in "
meiner" XppErrorsys.PRG lande ...
Frage : gibt es Umstände das man trotz "
eigener" XppErrorsys.PRG in der "
orginal" Errorsys.001 landet
![Question :?:](./images/smilies/question.gif)
Re: Private / Public / Threads / Errorsys
Verfasst: Sa, 11. Dez 2010 14:50
von michael32710
@Hubert
Bring mal das Stückchen Code zum Laufen:
Code: Alles auswählen
#include "memvar.ch"
procedure main()
cls
zPath := "C:\Programme"
aVar := SymbolInfo(MEMVAR_PRIVATE)
Qout("Dump PRIVATE Vars")
for nI:=1 to len(aVar)
Qout(aVar[nI,1], aVar[nI,2])
next
inkey(0)
return
Bei mir sieht der Screenshot so aus:
![Screenshot von BspPRIVATEdump](./download/file.php?id=754&sid=6429455995f7cffc8cd3a20bc5f2a170)
- Screenshot von BspPRIVATEdump
- bspPrivateDump.jpg (24.02 KiB) 9488 mal betrachtet
LG
Michael
Re: Private / Public / Threads / Errorsys
Verfasst: Sa, 11. Dez 2010 15:36
von michael32710
@Jimmy
Welche Fehlerbehandlung aktiv ist/wird hängt doch genau genommen nicht davon ab, welche ERRORSYS.PRG-entsprechende Code eingebunden sind, sondern davon was
liefert. Da heißt, welche Funktion im Fehlerfall angesprungen wird.
Ich muss mich oft durch alten Code von Kollegen hangeln. Da ist ErrorBlock() eine meiner Standardfragen im Debugger.
LG
Michael
Re: Private / Public / Threads / Errorsys
Verfasst: Sa, 11. Dez 2010 17:49
von brandelh
michael32710 hat geschrieben:@Hubert
Bring mal das Stückchen Code zum Laufen:
Ich habe mit der Funktion noch nie gearbeitet, PRIVATE und PUBLIC habe ich schon seit Clipper 5.x so weit wie möglich eliminiert.
Laut Beschreibung müsste der 2. Paramter ein Array sein.
? aVar -> gibt sowas schön aus { ... , ... , ... }
Re: Private / Public / Threads / Errorsys
Verfasst: Sa, 11. Dez 2010 18:07
von michael32710
@Hubert
Laut Beschreibung müsste der 2. Paramter ein Array sein.
Welcher zweite Parameter? In meiner Doku hat SymbolInfo() nur einen Parameter
Syntax
SymbolInfo( [<nDefine>] ) --> aReturn
LG
Michael
Re: Private / Public / Threads / Errorsys
Verfasst: Sa, 11. Dez 2010 18:10
von Jan
Hallo Michael,
wie kommst Du jetzt auf SymbolInfo()?
Jan
Re: Private / Public / Threads / Errorsys
Verfasst: Sa, 11. Dez 2010 18:11
von michael32710
@Hubert
Ach so, kapiere, Du beziehst Dich auf den Screenshot von mir.
Nein, in dem Moment wo SymbolInfo() ausgewertet wird ist eben aVar noch kein Array! Das ist der Witz an dem Beispiel
Grüße
Michael
Re: Private / Public / Threads / Errorsys
Verfasst: Sa, 11. Dez 2010 18:31
von michael32710
@Jan
Auf SymbolInfo() komme ich, weil meiner Meinung nach bei Hubert die Frage entstanden war:
Wie vereinbart Xbase per Default-Einstellung eine Variable (public oder private), die entsteht, wenn im Code "ohne weiteres" so was steht wie
Und mein Vorschlag war: Befrage SymbolInfo(MEMVAR_PRIVATE) und SymbolInfo(MEMVAR_PUBLIC) und Du wirst es erfahren.
LG
Michael
Re: Private / Public / Threads / Errorsys
Verfasst: Sa, 11. Dez 2010 21:03
von brandelh
Hallo Michael,
dann schau dir deinen Code und die Antwort nochmal genau an
PS: Mein 2. Parameter sollte tatsächlich die 2. Dimension des Antwortarray sein ... aber ich habe auch nicht ganz richtig gelesen
am Anfang dieser Zeile entsteht zunächst zPath mit NIL, welchem sofort c:\Programme zugewiesen wird:
Somit gilt ab der nächsten Zeile:
nun zu dieser:
am Anfang dieser Zeile entsteht aVar mit NIL !
Und deshalb ermittelt auch SymbolInfo() diese Zeilen:
und speichert das Array dann in aVar. Sobald dann deine Schleife kommt, enthält aVar den Inhalt:
und genau diesen Inhalt gibt deine Funktion auch aus
Code: Alles auswählen
Qout("Dump PRIVATE Vars")
for nI:=1 to len(aVar)
Qout(aVar[nI,1], aVar[nI,2])
next
=>
Wenn du also beweisen wolltest, dass zPath nicht sofort angelegt wurde, muss ich dir widersprechen.
Bewiesen hast du hingegen, dass JEDE Variable SOFORT mit NIL angelegt wird und erst danach die Zuweisung von z.B. := erfolgt.
UND dass man höllisch aufpassen muss um das Ergebnis nicht durch "PRIVATE" Nebenwirkungen zu verfälschen
Wenn man also tatsächlich die PRIVATEs testen will, dann muss man LOCALs verwenden:
Code: Alles auswählen
local aVar, x
memvar BinIchSchonDa
...
nWert := 1
zPath := "C:\Programme"
aVar := SymbolInfo(MEMVAR_PRIVATE)
for x := 1 to len(aVar)
? aVar
next
...
hier erhält man diese Ausgabe:
Die Variable
BinIchSchonDa wird nicht erscheinen, da diese noch nicht angelegt wurde !
PRIVATE oder direkte Zuweisungen legen memvars an, nicht aber MEMVAR !
Schließlich könnte sich MEMVAR ja auch auf eine übergeordnete PRIVATE oder PUBLIC beziehen
![Wink :wink:](./images/smilies/wink.gif)
Re: Private / Public / Threads / Errorsys
Verfasst: So, 12. Dez 2010 1:20
von michael32710
@Hubert
Beweisen wollte ich direkt gar nichts. Ich habe lediglich eine Empfehlung zu Deiner Antwort auf Tom weiter oben geben wollen.
da bin ich auch anderer Meinung, zur Laufzeit wird das Programm, sobald es an diese Stelle kommt, eine PUBLIC erzeugen und diese mit NIL belegen !
Nämlich SymbolInfo() zu nutzen, um an einer konkreten Programmstelle in Erfahrung zu bringen, wie das Programm die Sache sieht. Und dann wollte ich in dem Beispiel noch darauf hinweisen, dass eine Variable, wenn sie ohne Deklaration verwendet wird und es keine offene Datei mit einem Feld dieses Namens gibt, immer eine PRIVATE ist.
Was Du zu MEMVAR schreibst, ist aus meiner Sicht korrekt. MEMVAR ist für mich immer nur eine Art Compiler-Anweisung, die dem Compiler hilft Speicher-Variablen, die nicht LOCAL oder STATIC deklariert sind, von (namensgleichen) Feld-Namen zu unterscheiden.
LG
Michael
Re: Private / Public / Threads / Errorsys
Verfasst: So, 12. Dez 2010 8:08
von AUGE_OHR
michael32710 hat geschrieben:@Jimmy
Welche Fehlerbehandlung aktiv ist/wird hängt doch genau genommen nicht davon ab, welche ERRORSYS.PRG-entsprechende Code eingebunden sind, sondern davon was
liefert. Da heißt, welche Funktion im Fehlerfall angesprungen wird.l
hm ... guter Einwand
Code: Alles auswählen
bSaveError := ErrorBlock()
ErrorBlock( {|e| Break(e)} )
BEGIN SEQUENCE
...
RECOVER USING oError
ErrorBlock( bSaveError )
..
END SEQUENCE
ErrorBlock( bSaveError )
ich verwende den Errorblock "eigentlich" nur mit {|e| Break(e)}, aber ich werde ich alle noch mal kontrollieren.
hm ... wie kann ich den "kontrollieren" ob der gerade "aktive" Errorblock der "originale"
ist ?
die Function StandardEH() ist ja STATIC in der XppErrorsys.PRG ... soll/muss man das ändern ?
Ich fragte deshalb weil ich nun der Meinung bin das ich in solchen Fällen gar nicht in "
meiner" Errorsys lande
... es "fehlen" sämtliche "Modifikationen" wie ALIAS(), RECNO() etc.
p.s. vielleicht sollten wir den Thread aufteilen weil die PUBLIC/PRIVATE Problem und die XppErrorsys wohl nicht unbedingt zusammen hängen.
Re: Private / Public / Threads / Errorsys
Verfasst: Di, 18. Jan 2011 12:52
von michael32710
Hallo,
für Leidensgenossen, in deren Code noch Dynamische Variablen herumgeistern, habe ich eine kleine Erweiterung für das ErrorSys.prg anzubieten, die dem XPPERROR.LOG eine Liste der dynamischen Variablen hinzufügt (bei den PRIVATEs steht "(H)" für hidden und "(V)" für visible):
- ------------------------------------------------------------------------------
DYNAMIC VARs:
------------------------------------------------------------------------------
PUBLIC-Variablen (4):
1. AppObject : {}
2. GetList : {}
3. oDesktop : XbpIWindow
4. PromptList : {}
PRIVATE-Variablen (2):
1. cMyVar (H): Content1
2. cMyVar (V): Content2
Der Code dazu:
Code: Alles auswählen
/* Dynamische Variablen auflisten */
STATIC FUNCTION VarLog()
? Replicate( "-", 78 )
? "DYNAMIC VARs:"
? Replicate( "-", 78 )
? VarDump(MEMVAR_PUBLIC)
? VarDump(MEMVAR_PRIVATE)
return NIL
/* Variablenliste erzeugen */
STATIC FUNCTION VarDump(nMemVar_Modus)
local cVarDump := ""
local cCrLf := chr(13)+chr(10)
local cTab := chr(9)
local nLimit := 49152 // Limit: 48 KB fuer Rueckgabe cVarDump
local lPrivate := (nMemVar_Modus=MEMVAR_PRIVATE)
local cCaption := iif(lPrivate, "PRIVATE-Variablen", "PUBLIC-Variablen")
local aVarList := Symbolinfo(nMemVar_Modus)
local nLen := len(aVarList)
if nLen>0
ASort( aVarList,,, {|aX,aY| upper(aX[1]) < upper(aY[1]) } )
cVarDump += cCaption + " ("+ltrim(str(nLen))+"):" + cCrLf
aeval(aVarList, {|x,i| cVarDump += cTab + str(i,3,0)+". " + padr(x[1],15) + iif(lPrivate, iif(x[3]," (V)", " (H)"), "")+": " + Var2Char(x[2]) + cCrLf } )
else
cVarDump += "KEINE " + cCaption + cCrLf
endif
if len(cVarDump)>nLimit
cVarDump := left(cVarDump, nLimit)
endif
return cVarDump
Die Funktion VarLog() könnte man z.B. im ErrorSys.prg-Original in Zeile 397 einfügen:
Code: Alles auswählen
// Code-Ausschnitt aus ErrorSys.prg
...
IF IsMethod( oError, "getCallstack" )
? oError:getCallstack( Chr(13) + Chr(10) )
ELSE
DO WHILE ! Empty( ProcName(++i) )
? EHS_CALLED_FROM, Trim( ProcName(i) ) + "(" + ;
LTrim( Str( ProcLine(i) ) ) + ")"
ENDDO
ENDIF
?
VarLog() // <--------------------- Variablen-Liste
SET ALTERNATE TO
SET ALTERNATE OFF
Liebe Grüße
Michael