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
Grrr
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...
Regards,
Willie
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:
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...
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
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...
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:
>>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...
Thank you,
Jean-Luc
But I need the caption for the shortcut purpose. &Save for example.
Jean-Luc
I think that WinPrest will be improved in 2.7 if I find the trouble !
Jean-Luc
Geoff tries to make us believe he is the inventor of the log file ;-)
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
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
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
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:
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
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:
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:
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...
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
11:34 pm.... not so late for programmers !
Jean-Luc
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
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:
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
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
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?
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:
Thanx I was curious.
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...