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:

Code: Alles auswählen

    PublicVar():zPath := "meinNeuerPfad"
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 :?:

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
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

Code: Alles auswählen

ErrorBlock() // --> bLastErrorHandler
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 :D

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

Code: Alles auswählen

zPath := ""
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 :wink:

am Anfang dieser Zeile entsteht zunächst zPath mit NIL, welchem sofort c:\Programme zugewiesen wird:

Code: Alles auswählen

zPath := "C:\Programme" 
Somit gilt ab der nächsten Zeile:

Code: Alles auswählen

zPath == "C:\Programme" 
nun zu dieser:

Code: Alles auswählen

aVar := SymbolInfo(MEMVAR_PRIVATE)
am Anfang dieser Zeile entsteht aVar mit NIL !
Und deshalb ermittelt auch SymbolInfo() diese Zeilen:

Code: Alles auswählen

aVar   NIL
zPath  "C:\Programme"
und speichert das Array dann in aVar. Sobald dann deine Schleife kommt, enthält aVar den Inhalt:

Code: Alles auswählen

aVar   NIL
zPath  "C:\Programme"
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
=>

Code: Alles auswählen

Dump PRIVATE Vars
aVar   NIL
zPath  "C:\Programme"
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 :badgrin:

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:

Code: Alles auswählen

{"nWert",1,.t.}
{"zPath","C:\Programme",.t. 
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 :idea: :wink:

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

Code: Alles auswählen

ErrorBlock() // --> bLastErrorHandler
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"

Code: Alles auswählen

(ERRORBLOCK( { | o | StandardEH( o ) } ))
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