Private / Public / Threads / Errorsys
Moderator: Moderatoren
- brandelh
- Foren-Moderator
- Beiträge: 15710
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 73 Mal
- Danksagung erhalten: 38 Mal
- Kontaktdaten:
Re: Private / Public / Threads / Errorsys
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.
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.
Gruß
Hubert
Hubert
- Tom
- Der Entwickler von "Deep Thought"
- Beiträge: 9394
- Registriert: Do, 22. Sep 2005 23:11
- Wohnort: Berlin
- Hat sich bedankt: 105 Mal
- Danksagung erhalten: 364 Mal
- Kontaktdaten:
Re: Private / Public / Threads / Errorsys
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.
Herzlich,
Tom
Tom
Re: Private / Public / Threads / Errorsys
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.
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
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
Code: Alles auswählen
PublicVar():zPath := "meinNeuerPfad"
mfg
Christian
- brandelh
- Foren-Moderator
- Beiträge: 15710
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 73 Mal
- Danksagung erhalten: 38 Mal
- Kontaktdaten:
Re: Private / Public / Threads / Errorsys
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 !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.
Ab diesem Moment existiert die Variable und Valtype() gibt keine Fehlermeldung.
Gruß
Hubert
Hubert
- AUGE_OHR
- Marvin
- Beiträge: 12913
- Registriert: Do, 16. Mär 2006 7:55
- Wohnort: Hamburg
- Hat sich bedankt: 19 Mal
- Danksagung erhalten: 46 Mal
Re: Private / Public / Threads / Errorsys
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
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
gruss by OHR
Jimmy
Jimmy
- michael32710
- UDF-Programmierer
- Beiträge: 76
- Registriert: Sa, 17. Nov 2007 11:02
- Wohnort: Niedersachsen
- Kontaktdaten:
Re: Private / Public / Threads / Errorsys
@Hubert
Bring mal das Stückchen Code zum Laufen:
Bei mir sieht der Screenshot so aus:
LG
Michael
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
Michael
- michael32710
- UDF-Programmierer
- Beiträge: 76
- Registriert: Sa, 17. Nov 2007 11:02
- Wohnort: Niedersachsen
- Kontaktdaten:
Re: Private / Public / Threads / Errorsys
@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
Welche Fehlerbehandlung aktiv ist/wird hängt doch genau genommen nicht davon ab, welche ERRORSYS.PRG-entsprechende Code eingebunden sind, sondern davon was
Code: Alles auswählen
ErrorBlock() // --> bLastErrorHandler
Ich muss mich oft durch alten Code von Kollegen hangeln. Da ist ErrorBlock() eine meiner Standardfragen im Debugger.
LG
Michael
- brandelh
- Foren-Moderator
- Beiträge: 15710
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 73 Mal
- Danksagung erhalten: 38 Mal
- Kontaktdaten:
Re: Private / Public / Threads / Errorsys
Ich habe mit der Funktion noch nie gearbeitet, PRIVATE und PUBLIC habe ich schon seit Clipper 5.x so weit wie möglich eliminiert.michael32710 hat geschrieben:@Hubert
Bring mal das Stückchen Code zum Laufen:
Laut Beschreibung müsste der 2. Paramter ein Array sein.
? aVar -> gibt sowas schön aus { ... , ... , ... }
Gruß
Hubert
Hubert
- michael32710
- UDF-Programmierer
- Beiträge: 76
- Registriert: Sa, 17. Nov 2007 11:02
- Wohnort: Niedersachsen
- Kontaktdaten:
Re: Private / Public / Threads / Errorsys
@Hubert
Michael
Welcher zweite Parameter? In meiner Doku hat SymbolInfo() nur einen ParameterLaut Beschreibung müsste der 2. Paramter ein Array sein.
LGSyntax
SymbolInfo( [<nDefine>] ) --> aReturn
Michael
- Jan
- Marvin
- Beiträge: 14662
- Registriert: Fr, 23. Sep 2005 18:23
- Wohnort: 49328 Melle
- Hat sich bedankt: 21 Mal
- Danksagung erhalten: 88 Mal
- Kontaktdaten:
Re: Private / Public / Threads / Errorsys
Hallo Michael,
wie kommst Du jetzt auf SymbolInfo()?
Jan
wie kommst Du jetzt auf SymbolInfo()?
Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
- michael32710
- UDF-Programmierer
- Beiträge: 76
- Registriert: Sa, 17. Nov 2007 11:02
- Wohnort: Niedersachsen
- Kontaktdaten:
Re: Private / Public / Threads / Errorsys
@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
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
- michael32710
- UDF-Programmierer
- Beiträge: 76
- Registriert: Sa, 17. Nov 2007 11:02
- Wohnort: Niedersachsen
- Kontaktdaten:
Re: Private / Public / Threads / Errorsys
@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
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
Code: Alles auswählen
zPath := ""
LG
Michael
- brandelh
- Foren-Moderator
- Beiträge: 15710
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 73 Mal
- Danksagung erhalten: 38 Mal
- Kontaktdaten:
Re: Private / Public / Threads / Errorsys
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
=>
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:
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
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:
Code: Alles auswählen
zPath := "C:\Programme"
Code: Alles auswählen
zPath == "C:\Programme"
Code: Alles auswählen
aVar := SymbolInfo(MEMVAR_PRIVATE)
Und deshalb ermittelt auch SymbolInfo() diese Zeilen:
Code: Alles auswählen
aVar NIL
zPath "C:\Programme"
Code: Alles auswählen
aVar NIL
zPath "C:\Programme"
Code: Alles auswählen
Qout("Dump PRIVATE Vars")
for nI:=1 to len(aVar)
Qout(aVar[nI,1], aVar[nI,2])
next
Code: Alles auswählen
Dump PRIVATE Vars
aVar NIL
zPath "C:\Programme"
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
...
Code: Alles auswählen
{"nWert",1,.t.}
{"zPath","C:\Programme",.t.
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
Gruß
Hubert
Hubert
- michael32710
- UDF-Programmierer
- Beiträge: 76
- Registriert: Sa, 17. Nov 2007 11:02
- Wohnort: Niedersachsen
- Kontaktdaten:
Re: Private / Public / Threads / Errorsys
@Hubert
Beweisen wollte ich direkt gar nichts. Ich habe lediglich eine Empfehlung zu Deiner Antwort auf Tom weiter oben geben wollen.
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
Beweisen wollte ich direkt gar nichts. Ich habe lediglich eine Empfehlung zu Deiner Antwort auf Tom weiter oben geben wollen.
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.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 !
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
Zuletzt geändert von michael32710 am So, 12. Dez 2010 16:42, insgesamt 1-mal geändert.
- AUGE_OHR
- Marvin
- Beiträge: 12913
- Registriert: Do, 16. Mär 2006 7:55
- Wohnort: Hamburg
- Hat sich bedankt: 19 Mal
- Danksagung erhalten: 46 Mal
Re: Private / Public / Threads / Errorsys
hm ... guter Einwandmichael32710 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 wasliefert. Da heißt, welche Funktion im Fehlerfall angesprungen wird.lCode: Alles auswählen
ErrorBlock() // --> bLastErrorHandler
Code: Alles auswählen
bSaveError := ErrorBlock()
ErrorBlock( {|e| Break(e)} )
BEGIN SEQUENCE
...
RECOVER USING oError
ErrorBlock( bSaveError )
..
END SEQUENCE
ErrorBlock( bSaveError )
hm ... wie kann ich den "kontrollieren" ob der gerade "aktive" Errorblock der "originale"
Code: Alles auswählen
(ERRORBLOCK( { | o | StandardEH( o ) } ))
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.
gruss by OHR
Jimmy
Jimmy
- michael32710
- UDF-Programmierer
- Beiträge: 76
- Registriert: Sa, 17. Nov 2007 11:02
- Wohnort: Niedersachsen
- Kontaktdaten:
Re: Private / Public / Threads / Errorsys
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):
Die Funktion VarLog() könnte man z.B. im ErrorSys.prg-Original in Zeile 397 einfügen:
Liebe Grüße
Michael
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
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
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
Michael