Private / Public / Threads / Errorsys

Eigentlich ist mir die Frage peinlich, aber es kann sonst niemand helfen ... :)

Moderator: Moderatoren

ist deine Xbase++ Application multi Thread fähig

Ja
15
75%
Nein
5
25%
ich weiss nicht was ein Thread in Xbase++ ist
0
Keine Stimmen
 
Insgesamt abgegebene Stimmen: 20

Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Private / Public / Threads / Errorsys

Beitrag 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.
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9355
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Private / Public / Threads / Errorsys

Beitrag 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.
Herzlich,
Tom
Christian
Cut&Paste-Entwickler
Cut&Paste-Entwickler
Beiträge: 44
Registriert: Mi, 18. Jul 2007 15:05

Re: Private / Public / Threads / Errorsys

Beitrag 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
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Private / Public / Threads / Errorsys

Beitrag 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.
Gruß
Hubert
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Private / Public / Threads / Errorsys

Beitrag 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 :?:
gruss by OHR
Jimmy
Benutzeravatar
michael32710
UDF-Programmierer
UDF-Programmierer
Beiträge: 76
Registriert: Sa, 17. Nov 2007 11:02
Wohnort: Niedersachsen
Kontaktdaten:

Re: Private / Public / Threads / Errorsys

Beitrag 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) 9303 mal betrachtet
LG
Michael
Benutzeravatar
michael32710
UDF-Programmierer
UDF-Programmierer
Beiträge: 76
Registriert: Sa, 17. Nov 2007 11:02
Wohnort: Niedersachsen
Kontaktdaten:

Re: Private / Public / Threads / Errorsys

Beitrag 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
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Private / Public / Threads / Errorsys

Beitrag 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 { ... , ... , ... }
Gruß
Hubert
Benutzeravatar
michael32710
UDF-Programmierer
UDF-Programmierer
Beiträge: 76
Registriert: Sa, 17. Nov 2007 11:02
Wohnort: Niedersachsen
Kontaktdaten:

Re: Private / Public / Threads / Errorsys

Beitrag 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
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
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

Beitrag von Jan »

Hallo Michael,

wie kommst Du jetzt auf SymbolInfo()?

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
michael32710
UDF-Programmierer
UDF-Programmierer
Beiträge: 76
Registriert: Sa, 17. Nov 2007 11:02
Wohnort: Niedersachsen
Kontaktdaten:

Re: Private / Public / Threads / Errorsys

Beitrag 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
Benutzeravatar
michael32710
UDF-Programmierer
UDF-Programmierer
Beiträge: 76
Registriert: Sa, 17. Nov 2007 11:02
Wohnort: Niedersachsen
Kontaktdaten:

Re: Private / Public / Threads / Errorsys

Beitrag 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
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Private / Public / Threads / Errorsys

Beitrag 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:
Gruß
Hubert
Benutzeravatar
michael32710
UDF-Programmierer
UDF-Programmierer
Beiträge: 76
Registriert: Sa, 17. Nov 2007 11:02
Wohnort: Niedersachsen
Kontaktdaten:

Re: Private / Public / Threads / Errorsys

Beitrag 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
Zuletzt geändert von michael32710 am So, 12. Dez 2010 16:42, insgesamt 1-mal geändert.
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Private / Public / Threads / Errorsys

Beitrag 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.
gruss by OHR
Jimmy
Benutzeravatar
michael32710
UDF-Programmierer
UDF-Programmierer
Beiträge: 76
Registriert: Sa, 17. Nov 2007 11:02
Wohnort: Niedersachsen
Kontaktdaten:

Re: Private / Public / Threads / Errorsys

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