Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Strange behavior

53 views
Skip to first unread message

Jean-Luc Stassen

unread,
Nov 25, 2005, 5:08:56 AM11/25/05
to
Hi all,

I was still fighting for monthes with unpredicable error in my app
compiled in vo27b.
For example: access violation when leaving the app. This error was
coming after the self:exec() of the start function (and after the
queryclose of the standardshell) or HyperLabel:Axit that is not found.

Today, I have imported the Manifest module. Just to try. I don't have
the errors anymore... but... all my menu and look is changed... due to
the windows xp style...

It's a dilema: update all my menu and button.. or deal with the error !

Any suggestion ?


Jean-Luc

Jean-Luc Stassen

unread,
Nov 25, 2005, 5:32:14 AM11/25/05
to

There is a big problem for me: caption of pushbutton with an image is
printed over the image... not very beautifull.. And I need the caption,
because it make the short cut: &Save....

Grrr

Nick Friend

unread,
Nov 25, 2005, 7:29:05 AM11/25/05
to
Jean-Luc,

The access violation (5333 error I presume) is almost certainly
indicative of an error somewhere in the app. It'd be far better to spend
time chasing it down...

Nick

In article <1132914734.2...@f14g2000cwb.googlegroups.com>,
j...@igsoft.be says...

Williem

unread,
Nov 25, 2005, 8:00:51 AM11/25/05
to
Jean-Luc,
Do you need the caption at run-time or design time. For me, I use a
subclassed push-button and i set the caption to "" if the button has a
picture. It is a one line change. I believe Jamal came up with it
shortly after 2.7 was released. I can repost if you are interested.

Regards,

Willie

Geoff Schaller

unread,
Nov 25, 2005, 8:02:30 PM11/25/05
to
Jean-Luc,

Firstly, please read the Readmes and What's New documents. They list in
some detail the changes relating to Windows themes and the impact on
various controls. There will be many clues to help you with this. Once
you have read this and still cannot achieve what you want, come back to
the ng with specific code and I am sure we can help. We all survived
<bg>.

Secondly, the shut down sequence is now a little tighter and demands you
do things 'properly'. For instance, load any sample, create the exe, run
it, close it and will not give this problem. Hence something you are
doing in your app causes the problem and you need to isolate your
closure sequences in your classes to find out where this happens from.
Again, we've all been through this and come out the end unscathed. You
will too <g>.

Geoff


"Jean-Luc Stassen" <j...@igsoft.be> wrote in message
news:1132914734.2...@f14g2000cwb.googlegroups.com:

Eric Hourant

unread,
Nov 26, 2005, 4:03:43 AM11/26/05
to
Jean-Luc,
I would suggest that you include the ShowGCDump function (you can find it
somewhere in this NG). From time to time, while using your app, just run
this dump and take a look on all the objects, arrays, ... that are left in
memory where they should not.

You can also set :
PROCEDURE StartUp AS VOID PASCAL _INIT3
_RegisterExit( @ShowGCDump() )
RETURN

to run the dump automatically when you leave the program.

Your problem stays somewhere in your code. It is just being shown up when
you leave the program.

HTH

Eric


"Jean-Luc Stassen" <j...@igsoft.be> a écrit dans le message de news:
1132913336....@z14g2000cwz.googlegroups.com...

Geoff Schaller

unread,
Nov 26, 2005, 4:23:22 AM11/26/05
to
FUNCTION ShowGCDump() AS VOID PASCAL

LOCAL pGCEntry AS _GCENTRY
LOCAL pGCDump AS _GCDUMP
LOCAL dwItems AS DWORD
LOCAL dwMax AS DWORD
LOCAL nItem AS DWORD
LOCAL cDumpFilename AS STRING
LOCAL oLog AS GCSLogFile
LOCAL oTemp AS OBJECT

DoEvents()
CollectForced()
DynLock() // lock up dynamic mem to obtain accurate result

dwMax:=100
pGCDump:=MemAlloc(_SIZEOF(DWORD)+(dwMax*_SIZEOF(_GCENTRY)))
pGCDump.nEntryCount:=dwMax
dwItems:=CreateGCDump(pGCDump,6) // 0=All, 7=Strings, 5=Arrays,
3=FLOATs, 6=Objects
IF dwItems > 0
cDumpFilename := gcDumpFileRoot+"_" +
Right(DToS(Today()),4)+Left(Time(),2)+SubStr(Time(),4,2)+".log"
DebugOutputNoTrace("GCDump Found Items",dwItems, "GC Dump log file",
cDumpFilename)
oLog := GCSLogFile{cDumpFilename,,,,FALSE} // create new file each
time
IF !oLog:IsOpen
DebugOutput("Failed to create log file")
ENDIF
oLog:Write("Active references to dynamic memory: "+NTrim(dwItems))
oLog:Write("---------------------------------------------------------")
oLog:Write()
IF dwItems = dwMax
oLog:Write(" Maximum Entries inserted - Possibly more existed")
oLog:Write()
ENDIF
pGCEntry:=PTR(_CAST,DWORD(_CAST,pGCDump)+_SIZEOF(DWORD))
FOR nItem := 1 UPTO dwItems
oLog:Write("Created by :
"+Iif(pGCEntry.nGCType==GC_TYPE_STACK,"Compiler","RegisterKID()"))
oLog:Write("Dyn.Addr. : "+AsString(pGCEntry.pDynMem) + " Ref: " +
AsString(pGCEntry.ppRefDynMem))
oLog:Write("Size : "+NTrim(pGCEntry.nSize))
oLog:Write("Type : "+GCVarType(pGCEntry.nVarType))
oLog:Write("Value : "+Psz2String(@pGCEntry.abValue[1]))
oLog:Write("---------------------------------------------------------")
pGCEntry:=pGCEntry+1
NEXT
IF !oLog:Close()
DebugOutput("Error closing GCDumpFile")
ELSE
ShellExecute(NULL_PTR,
PSZ("OPEN"),String2Psz(oLog:Filename),NULL_PSZ,NULL_PSZ,SW_SHOWNORMAL)
ENDIF
ELSE
DebugOutputNoTrace("Exiting GCDump - all objects destroyed")
ENDIF
MemFree(pGCDump)
gcDumpFileRoot := NULL_STRING // clear global string

DynUnLock()

RETURN

Eric Hourant

unread,
Nov 26, 2005, 6:37:12 AM11/26/05
to
Geoff,

Thanks for Jean-Luc.

Greetings from frozen Belgium (-1°C, 20 cm snow).

Eric


"Geoff Schaller" <geo...@softxxwareobjectives.com.au> a écrit dans le
message de news: 4388...@dnews.tpgi.com.au...

Geoff Schaller

unread,
Nov 26, 2005, 7:17:11 AM11/26/05
to
<g>

It was only 22C here today but the sun shone the whole day and it was
really nice in the garden.

"Eric Hourant" <ehou...@nospamno-echo-soft.com> wrote in message
news:43884a84$0$3696$ba62...@news.skynet.be:

Eric Hourant

unread,
Nov 26, 2005, 8:15:07 AM11/26/05
to
Geoff,

>>It was only 22C here<<

I hate you !

;-)


"Geoff Schaller" <geo...@softxxwareobjectives.com.au> a écrit dans le

message de news: 4388521f$1...@dnews.tpgi.com.au...

Jean-Luc Stassen

unread,
Nov 28, 2005, 12:01:01 PM11/28/05
to
Thanks a lot Eric and Geoff. But Geof, could you tell me what is the
class GCSLogFile ?

Thank you,
Jean-Luc

Jean-Luc Stassen

unread,
Nov 28, 2005, 12:01:53 PM11/28/05
to
Thanks Willem,

But I need the caption for the shortcut purpose. &Save for example.


Jean-Luc

Jean-Luc Stassen

unread,
Nov 28, 2005, 12:03:00 PM11/28/05
to
Thanks Eric...

I think that WinPrest will be improved in 2.7 if I find the trouble !

Jean-Luc

Eric Hourant

unread,
Nov 28, 2005, 12:28:56 PM11/28/05
to
>>what is the class GCSLogFile ? <<
G stands for Geoff
SC stands for Schaller
LogFile is a generic name to write a simple text file with the result.

Geoff tries to make us believe he is the inventor of the log file ;-)


Eric


Karl Faller

unread,
Nov 28, 2005, 12:46:31 PM11/28/05
to
Eric,

>>>what is the class GCSLogFile ? <<
>G stands for Geoff
>SC stands for Schaller
Backwards ? <s,cr>
Karl

Jean-Luc Stassen

unread,
Nov 28, 2005, 2:37:33 PM11/28/05
to
Eric,

I suspected something like that but I still don't know from what class
inherit this one... Write is a methode of the console class... but I
don't find any other class fo that...
Ok I finaly rewrite a similar class to manage that and now here the
file created:


Active references to dynamic memory: 17
---------------------------------------------------------

Created by : Compiler
Dyn.Addr. : 0x04DE09F4 Ref: 0x02B6D030
Size : 56
Value : {(0x0038)0x04DE09F4} CLASS APP
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE1AA8 Ref: 0x100B44B8
Size : 292
Value : {(0x0124)0x04DE1AA8} CLASS STANDARDSHELLWINDOW
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x07FE5EEC
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x07FE5F1C
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x07FE5F4C
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x07FE5F7C
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x07FE5FAC
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x07FE5FDC
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x0466FE8C
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x0466FEBC
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x0466FEEC
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x0466FF1C
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x0466FF4C
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x0466FF7C
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x0466FFAC
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x0466FFDC
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x04DE2A20 Ref: 0x07FE6014
Size : 40
Value : {(0x0028)0x04DE2A20} CLASS EMPTYSHELLMENU

But I don't know if it's good or not ??


Jean-Luc

Jean-Luc Stassen

unread,
Nov 28, 2005, 3:01:56 PM11/28/05
to
Geof,

I have had a 5333 now, and here is the log file generated when leaving:

Active references to dynamic memory: 2
---------------------------------------------------------

Created by : Compiler
Dyn.Addr. : 0x045109F4 Ref: 0x0129D030
Size : 56
Value : {(0x0038)0x045109F4} CLASS APP
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x045116AC Ref: 0x100B44B8
Size : 292
Value : {(0x0124)0x045116AC} CLASS STANDARDSHELLWINDOW
---------------------------------------------------------

What can be wrong here ?

I provide also my Queryclose Method:

METHOD QueryClose(oEvent) CLASS StandardShellWindow

LOCAL lAllowClose AS LOGIC
LOCAL oserver AS OBJECT
MEMVAR cnumcol,m_path
MEMVAR M_SOCPATH,otrad

lAllowClose := SUPER:QueryClose(oEvent)

// Kill the timer
SELF:RegisterTimer(0)

// un-log the worker
oserver:=collabor{}
oserver:setorder(1)
oserver:seek(cnumcol)
IF !oserver:eof
J_LOCKR(oserver,SELF)
oserver:userIN:=FALSE
J_COMUNLOCK(oserver,SELF)
ENDIF
oserver:close()

// un-log the user
oserver:=user{}
DO WHILE !oserver:eof
IF AllTrim(AsString(oserver:user)) == AllTrim(AsString(NetName()))
J_LOCKR(oserver,SELF)
oserver:userEROR:=FALSE
oserver:userIN:=FALSE
J_COMUNLOCK(oserver,SELF)
ENDIF
oserver:skip()
ENDDO
oserver:close()

// if asked synchronize the file on the local drive
IF READINI("SYNCHRO",M_SOCPATH+"gp.ini")=="O" .and.
M_PATH<>M_SOCPATH+"SYNCHRO\"
igsynchro()
ENDIF

// save combobox print size (in the toolbar)
WRITEINI("COMBOPRINTSIZE",M_SOCPATH+"WINPOS.INI",NTrim(SELF:oCB:size:width))

// otrad is a MEMVAR object. This is the dbserver with the translation
otrad:commit()
otrad:close()

RETURN lAllowClose

Am i doing something wrong ?

Jean-Luc

Jean-Luc Stassen

unread,
Nov 28, 2005, 3:26:40 PM11/28/05
to
Geof, Eric,

I ask you an advice:

METHOD Start() CLASS app
local oWin as StandardShellWindow
local ofile as myfile

oWin:=StandardShellWindow{self}
oWin:show()

ofile:=myfile{}
....
....
ofile:close()

// Must I add this ?
ofile:=NULL_OBJECT

Self:Exec()

// Must I add this ?
oWin:=NULL_OBJECT


Because with the showdump of Geof, all these variables stay open...
It seems (I touch wood here) that I don't have the error...; I Pray
8-)))


Jean-Luc

Geoff Schaller

unread,
Nov 28, 2005, 3:34:50 PM11/28/05
to
J-L,

Firstly, you do a lot of things in this method (function calls etc) that
could do anything so I don't really know - they pass in references to
the shell, for example. Why not make those function calls server class
methods?

Secondly, this is an abuse of the QueryClose concept <g>. All of this
kind of code belongs in the Close() method. In your case lAllowClose is
only ever TRUE.

Thirdly, this is not the important code. It's the Function Start and
Method Start that matter the most.

Fourthly, having Class App show in your GC Dump probably doesn't matter
because I suspect it still exists when you write your dump. So this
could also be true for the shellwindow.

Fifth, get in the habit of subclassing all classes you use so that you
can isolate your added behaviour from default baheviour. It makes it a
lot easier to fault-find.

So we need to see the point where the 5333 happens, not your QueryClose.

Geoff


"Jean-Luc Stassen" <j...@igsoft.be> wrote in message

news:1133208116.7...@g43g2000cwa.googlegroups.com:

Geoff Schaller

unread,
Nov 28, 2005, 3:37:54 PM11/28/05
to
J-L,

I just have my own log file class. I didn't like the VO one so I adapted
some code I got from this NG some time back:

ACCESS Buffer() CLASS GCSLogFile
RETURN SELF:sWriteString

CLASS GCSLogFile
PROTECT ptrHandle AS PTR // ptrHandle für das GCSLogFile
PROTECT sWriteString AS STRING // Zu schreibender Buffer
PROTECT lMakeCRLF AS LOGIC // Automatisches anfügen von CRLF
PROTECT lShDate AS LOGIC // Mitschreiben des Datums
PROTECT lShTime AS LOGIC // Mitschreiben der Zeit
PROTECT lOpen AS LOGIC // File konnte angelegt bwz geöffnet werden
PROTECT dwLastError AS DWORD // Letzter aufgetretner Fehler
PROTECT cFileName AS STRING // final name computed
PROTECT junk AS INT
PROTECT dwMaxReadLen AS DWORD // 18/11/04 AJ: Number of chars to read
per line
METHOD Close CLASS GCSLogFile

LOCAL lRet := TRUE AS LOGIC

IF SELF:lOpen
// Versuchen wir noch den verdammten Restbuffer ins File zu bringen
IF !Empty( SELF:sWriteString )
SELF:Write( SELF:sWriteString )
ENDIF
FCommit(ptrHandle)
lRet := FClose( ptrHandle )
IF !lRet
SELF:dwLastError := DosError()
ELSE
SELF:lOpen := FALSE
ENDIF
ENDIF

RETURN lRet


ACCESS IsOpen() CLASS GCSLogFile
RETURN SELF:lOpen

ACCESS LastError( ) CLASS GCSLogFile
RETURN SELF:dwLastError

METHOD Write( sString ) CLASS GCSLogFile

LOCAL lRet := FALSE AS LOGIC
// Zusammensetzen des zu schreibenden Strings
Default (@sString, "")

IF SELF:lShDate
SELF:sWriteString += DToS( Today() ) + " "
ENDIF

IF SELF:lShTime
SELF:sWriteString += Time() + " "
ENDIF

SELF:sWriteString += sString

IF SELF:lMakeCRLF
SELF:sWriteString += CRLF
ENDIF

// Wir wollen es ja auch hinten anhängen
FSeek( SELF:ptrHandle, 0, FS_END )

// Und rein in die Datei
IF FWrite( SELF:ptrHandle, SELF:sWriteString ) == SLen(
SELF:sWriteString )
SELF:sWriteString := ""
lRet := TRUE
ELSE
SELF:dwLastError := DosError()
ENDIF

RETURN lRet

METHOD Init( sFilename, lAutoCRLF, lDate, lTime, lAdditive, nMaxReadLen)
CLASS GCSLogFile

LOCAL oGlobal AS GCSGlobalObjectBase

// Set defaults where required - note we keep appending by default
Default(@sFilename, gcDumpFileRoot+".log")
Default(@lAdditive, TRUE) // append to existing file
Default(@lAutoCRLF, TRUE)
Default(@lDate, FALSE)
Default(@lTime, FALSE)
Default(@nMaxReadLen, 256) // 18/11/04 AJ

// put the log file in the errors directory unless a dir is specified
IF !Instr("\", sFilename)
oGlobal := GetGlobal()
sFilename := oGlobal:report_directory + sFilename
ENDIF

// Set internal variables
SELF:dwMaxReadLen := nMaxReadLen // 18/11/04 AJ
SELF:lShDate := lDate
SELF:lShTime := lTime
SELF:lMakeCRLF := lAutoCRLF
SELF:cFilename := sFileName

dwLastError := DosError()

// Open the file according to selected mode
DO CASE
CASE !File( sFileName )
SELF:ptrHandle := FCreate2( sFileName, FC_NORMAL )
CASE !lAdditive // new file anyway
SELF:ptrHandle := FCreate2( sFileName, FC_NORMAL )
OTHERWISE
SELF:ptrHandle := FOpen2( sFileName, FO_READWRITE + FO_SHARED )
ENDCASE

// überprüfen des Öffnes
IF SELF:ptrHandle == F_ERROR
SELF:dwLastError := DosError()
SELF:lOpen := FALSE
ELSE
SELF:lOpen := TRUE
ENDIF

RETURN SELF

ACCESS LineCount CLASS GCSLogFile

LOCAL dwLines AS DWORD
LOCAL Line AS STRING

dwLines := 0
DO WHILE !FEof(SELF:ptrHandle)
line := FReadLine(SELF:ptrHandle)
dwLines += 1
ENDDO

RETURN dwLines
METHOD ReadLine() CLASS GCSLogFile

LOCAL cLine AS STRING

cLine := FReadLine(SELF:ptrHandle, SELF:dwMaxReadLen) // 18/11/04 AJ:
Added dwMaxReadLen
SELF:dwLastError := DosError()

RETURN cLine

METHOD GoTop() CLASS GCSLogFile
FRewind(SELF:ptrHandle)
RETURN NIL
METHOD GoBottom() CLASS GCSLogFile
FSeek(SELF:ptrHandle, 0, FS_END)
RETURN NIL
ACCESS Eof CLASS GCSLogFile
RETURN FEof(SELF:ptrHandle)
ACCESS FileName CLASS GCSLogFile
RETURN cFilename

ACCESS Size CLASS GCSLogFile

LOCAL nSize AS INT

FSeek(SELF:ptrHandle, 0, FS_SET) // rewind
nSize := FSeek(SELF:ptrHandle, 0, FS_END) // go to end

RETURN nSize
METHOD Seek(nOffset, nStart) CLASS GCSLogFile

// returns logical not EOF as an indicator the seek worked
Default(@nStart, FS_RELATIVE)

FSeek(SELF:ptrHandle, nOffset, nStart)

RETURN !FEof(SELF:ptrHandle)
METHOD WriteLine(sString) CLASS GCSLogFile

LOCAL lRet := FALSE AS LOGIC
// Write and append a CRLF regardless, nodate/times etc
Default (@sString, "")

// Wir wollen es ja auch hinten anhängen
FSeek( SELF:ptrHandle, 0, FS_END )

// Und rein in die Datei
IF FWriteLine(SELF:ptrHandle, sString ) == SLen(sString)
lRet := TRUE
ELSE
SELF:dwLastError := DosError()
ENDIF

RETURN lRet


Geoff Schaller

unread,
Nov 28, 2005, 3:43:04 PM11/28/05
to
J-L,

Normally you would not need to null_object these things but again, we
don't know what they do. It might help clear the objects sooner I guess.
I also noticed earlier that you use memvars (you shouldn't - switch to
globals or ivars on the app class or something) but thshouldn't have an
effect on the outcome.

So what is oFile and why are you doing stuff here in the Start method?
Couldn't this be better handled as a process (method) of the shell
window class? Its all easier to trace what is going on.

Geoff

"Jean-Luc Stassen" <j...@igsoft.be> wrote in message

news:1133209600....@g43g2000cwa.googlegroups.com:

Geoff Schaller

unread,
Nov 28, 2005, 3:45:10 PM11/28/05
to
Which class uses emptyshellmenu???? <g>
I can guess.

So the menu is not destroying but it is reloading multiple times. How
might this come about?

Geoff


"Jean-Luc Stassen" <j...@igsoft.be> wrote in message

news:1133206653....@g44g2000cwa.googlegroups.com:

Eric Hourant

unread,
Nov 28, 2005, 5:19:22 PM11/28/05
to
Jean-Luc,
Geoff is right. The QueryClose method is just there to answer the question
"do you agree to close the window ?".
Imagine that your Super:QueryClose method replies false. So you are going to
kill the timer, unlock the user and all your stuff. But your window is still
open.
So you try to close it another time and ask a new QueryClose and try to
rekill the timer and to re-unlock the user ....

I do not say this is THE cause to your 5333 but this can one of the reason
to have it.

Another point : in your QueryClose method :
LOCAL oserver AS OBJECT
...
oserver:=collabor{}

Why do you declare oServer as an object and not a dbserver or a dataserver ?

Also after an oserver:close(), I always set oServer :=null_object. I do not
know if this can help the GC but it cannot hurt it.

I think that one of the diffrence between 2.5 (the version you are using)
and the 2.7 is that the 5333 are shown faster.

Read the excellent Geoff article about 5333 and you will understand better
how this can happen.

HTH

Eric

"Jean-Luc Stassen" <j...@igsoft.be> a écrit dans le message de news:
1133208116.7...@g43g2000cwa.googlegroups.com...

Jean-Luc Stassen

unread,
Nov 28, 2005, 5:32:11 PM11/28/05
to
Geoff,

I have found the problem with the menu. The menu is reloaded when
changing language or modifying access to some under-menu.
I have something like that:
// re-shower la shell si on change de langue
IF M_LANGUE<>M_LANGUE_START
SELF:Menu:Destroy()
SELF:Menu := EmptyShellMenu{ SELF }

I have add the destroy method, and now I only have one instance of the
menu. Good.

But for my start method... it's a long long method.... 714 lines !
Because I do a lot a things there... check user entry, check
installation code...

Do you suggest I must put all that code in a method of the
standardshell window and call it from the start method ?

NB: This the my last dump

Active references to dynamic memory: 3
---------------------------------------------------------

Created by : Compiler
Dyn.Addr. : 0x04510D30 Ref: 0x0129D030
Size : 56
Value : {(0x0038)0x04510D30} CLASS APP
---------------------------------------------------------
Created by : Compiler
Dyn.Addr. : 0x04510D30 Ref: 0x0012FF8C
Size : 56
Value : {(0x0038)0x04510D30} CLASS APP
---------------------------------------------------------
Created by : RegisterKid()
Dyn.Addr. : 0x045121B4 Ref: 0x100B44B8
Size : 292
Value : {(0x0124)0x045121B4} CLASS STANDARDSHELLWINDOW
---------------------------------------------------------

I miss still some function to make your ShowGCDump() function working:

DebugOutputNoTrace
DebugOutput
GCVarType
GCSGlobalObjectBase

I have found workaround to make it working... But it will be better
with these functions too...


Thank you for your help ?

Jean-Luc

Jean-Luc Stassen

unread,
Nov 28, 2005, 5:35:15 PM11/28/05
to

8-) ...Oops Geoff, please understand: "Thank you for your help !" and
not "Thank you for your help ?"

11:34 pm.... not so late for programmers !
Jean-Luc

Jean-Luc Stassen

unread,
Nov 28, 2005, 5:54:16 PM11/28/05
to
Geoff,

Why I use MEMVAR ? Because I need them in some DLL or Libraries... Is
there any other way ? GLOBAL are note visible in a library, only MEMVAR
can do that...

Am I wrong ?

Jean-Luc

Geoff Schaller

unread,
Nov 28, 2005, 6:27:09 PM11/28/05
to
Yes you are wrong <g>

Firstly I would contemplate subclassing your app object and putting your
'globals' in there as ivars. It is easy to get the app object anywhere
in your app if you create your own Function Start() and use the
following lines:

oApp := GCSApp{}
__SetAppObject(oApp)
SetGCSAppObject(oApp)
oApp:Start()
// clear the application object and null the global holding it
oApp := NULL_OBJECT
__SetAppObject(NULL_OBJECT)
SetGCSAppObject(NULL_OBJECT)
WCDCClear()

This code then allows you employ your own app class throughout and
strongly typed to your class name.

Inco conjunction with this (or alternately) you can use a global from a
DDLL like this:

FUNCTION GetGCSAppObject() AS GCSApp
RETURN goApp
STATIC GLOBAL goApp AS GCSApp
FUNCTION SetGCSAppObject(oApp)
goApp := oApp
RETURN NIL

Instead of the app object you could create a global object class and
treat it the same way. If you don't like the functional approach you can
always use SysObject{} to store and retrieve your global object class.

Geoff


"Jean-Luc Stassen" <j...@igsoft.be> wrote in message

news:1133218456.0...@g43g2000cwa.googlegroups.com:

Geoff Schaller

unread,
Nov 28, 2005, 6:33:57 PM11/28/05
to
J-L,

Good... progress <g>.

Now, your 714 lines in the start <sigh... bg>. Yes, break them up into
functional groups and make them method calls in your shell class. I
think this is best.

> DebugOutputNoTrace
> DebugOutput
> GCVarType
> GCSGlobalObjectBase

Well you can just comment out the use of these things, they are for
debugging but here is the code if you are interested:

FUNCTION DebugOutput()

LOCAL dwN, dwCount, dwActivation AS DWORD
LOCAL uValue AS USUAL
LOCAL cProcName, cOutput AS STRING

dwCount := PCount()
uValue := _GETFPARAM(1)
cProcName := ProcName(0)

IF cProcName = "DEBUG"
dwActivation := 1 // debug is on in this module
cProcName := ProcName(1)
IF cProcName = "DEBUG"
dwActivation := 2 // debug is on another debug function calling this
one
ENDIF
ELSE
dwActivation := 0
ENDIF
cOutput := ProcName(dwActivation) + " Line:" +
StrZero(ProcLine(dwActivation),4)+", " + AsString(uValue)

IF !IsNil(uValue)
FOR dwN := 2 UPTO dwCount
uValue := _GETFPARAM(dwN)
IF IsObject(uValue)
uValue := ClassName(uValue)
ENDIF
cOutput += ", " + AsString(uValue)
NEXT
// OutputDebugString() crashes for string lengths somewhere around 250
chars
IF SLen(cOutput) > 240
cOutput := Left(cOutput, 240) + "..."
ENDIF
ENDIF

_DebOut32(String2Psz(cOutput)) // allows use whilst in the IDE

RETURN NIL

FUNCTION DebugOutputNoTrace()

LOCAL cOutput AS STRING
LOCAL nN, nCount AS DWORD
LOCAL uValue AS USUAL

nCount := PCount()
uValue := _GETFPARAM(1)

IF !IsNil(uValue)
cOutput := AsString(uValue)
FOR nN := 2 UPTO nCount
uValue := _GETFPARAM(nN)
IF IsObject(uValue)
IF uValue = NULL_OBJECT
uValue := "NULL_OBJECT"
ELSE
uValue := ClassName(uValue)
ENDIF
ENDIF
cOutput += ", " + AsString(uValue)
NEXT
// OutputDebugString() crashes for string lengths somewhere around 250
chars
IF SLen(cOutput) > 240
cOutput := Left(cOutput, 240) + "..."
ENDIF
_DebOut32(String2Psz(cOutput)) // allows use whilst in the IDE
ENDIF

RETURN NIL

FUNCTION GCVarType( nType AS DWORD ) AS STRING STRICT

LOCAL cRet AS STRING

// using this function stops the ShowGCDump reporting the array it uses
DO CASE
CASE nType = 3
cRet := "FLOAT"
CASE nType = 5
cRet := "ARRAY"
CASE nType = 6
cRet := "OBJECT"
CASE nType = 7
cRet := "STRING"
OTHERWISE
cRet := "*****"
ENDCASE

RETURN cRet

Gary Stark

unread,
Nov 28, 2005, 7:15:08 PM11/28/05
to
Jean-Luc


Very much so.

You are correct i8n that globals, very frequently, have scoping issues
within foreign DLLs and libraries. They are best avoided.

Imstead, one of the more effective methods of addressing the issue of
so-called global variables is to consider them in a more object oriented
manner - they are "global" within the context of the application, aren't
they?

And your application has an App class, doesn't it?

Subclass the App class, make your "globals" properties of the app class,
wrap the GetAppObject() function to get around its strong typing, and
these problems just go away, never, ever to be seen again.

And you should have lots of examples of this stuff; just look at some of
the samples in your samples directory. There's heaps of them; you just
need to explore.


--
g.
Gary Stark
gst...@RedbacksWeb.com
http://www.RedbacksWeb.com

Gary Stark

unread,
Nov 28, 2005, 7:17:40 PM11/28/05
to
Geoff,

Interesting response from you. I note that you're advocating the App
Object approach as the first choice, in preference to the use of the
System Object.

What's prompted this change in your PoV?

Geoff Schaller

unread,
Nov 28, 2005, 8:33:09 PM11/28/05
to
Gary,

Functionally I have no preference but you and a few others seem to
favour the app object. Hence, if we're offering advice to others its
conceptually simpler for the correspondent to see a more united front.
Hence I've shelved my earlier preference for SysObject with AppObject.

I still like SysObject but we are now writing lots of little stand-alone
tools that have nothing but an exe. In this case, it is definitely
easier to just add the app object approach. Also, as we now always have
a subclassed app object, SysObject becomes a redundancy. Its more self
contained.

Hence my change of direction.

Cheers,

Geoff

"Gary Stark" <bogus...@yahoo.com> wrote in message
news:3v1l28F...@individual.net:

Gary Stark

unread,
Nov 28, 2005, 10:02:29 PM11/28/05
to
Geoff,

Thanx I was curious.

Meinhard Schnoor-Matriciani

unread,
Nov 29, 2005, 2:43:19 AM11/29/05
to
Hi Jean-Luc,

just a quick question, does your start function return something ? If not,
make it return a nil or a zero. I remember, that there was an error in the
stub code which expects that the start function return something. If nothing
was returned and accidently somehting is in the registers which is not zero,
the stub code is trying to access this, which ( sometimes, not always ) lead
to the 5333 while ending the application.

Regards,
Meinhard

"Jean-Luc Stassen" <j...@igsoft.be> schrieb im Newsbeitrag
news:1133197380....@f14g2000cwb.googlegroups.com...

0 new messages