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

SetMaxDynSpace blues

292 views
Skip to first unread message

Ameer Hussein

unread,
Mar 29, 2004, 1:59:10 PM3/29/04
to
Hi,

I encountered a serious issue while 'porting' a large project from VO
2.6 to Vo 2.7. The problem I found is related to SetMaxDynSpace:

Here's the test case:(basic console app)
==============================================================
FUNCTION Start(p)
LOCAL oCon AS Console
LOCAL count :=0 AS INT
LOCAL cThis AS STRING

SetMaxDynSize(128*1024*1024) // 128 MB

oCon := Console{}

/*1*/ DynLock()

WHILE TRUE
Count++
IF Mod(COUNT,64)==0
oCon:WriteLine("dING ...."+Str(COUNT)+"........"+Str
(DynInfoUsed()))
ENDIF
/*2*/ cThis:=Space(64*1024) // 64 KB string
ENDDO

RETURN
========================================================
The code attempts to use up dynamic memory eventually crashing the
program. The line marked /*1*/ locks dynamic memory so that GC is not
triggered, and the line marked /*2*/ allocated 64 KB strings. Since GC
is never triggered, strings allocated for cThis in previous loop
iterations are never freed and dynamic memory gets used up.

The program crashes while DynInfoUsed returns 32 MB although dynamic
memory size is set to 128 MB as you can see in the beginning of the
function!

Now, take this code to VO 26, remove the call to SetMaxDynSize and fix
your CA-Visual Objects/RunTime registery entry to use 128 MB Dynamic
memory and the code will run correctly, breaking when DynInfoUsed
returns around 128 MB. (vo 26 also seemed as if it did some garbage
collection although dynlock was in effect!!!)

Playing with the value passed to SetMaxDynSize does not change VO 27
behavior in anway! It's as if the call is completely ignored.

The application I was porting to 27 does run with only 32 MB of
dynamic memory but performance suffers, and setting dynamic memory
size to 64 MB or 128 MB if the machine can take the load allows users
to open many more data windows without running into memory related
issues. I'll have to postpone the upgrade until the issue is solved.

Any Ideas, workaround untill 2.7 patch comes up?

Geoff Schaller

unread,
Mar 30, 2004, 8:02:25 AM3/30/04
to
Did you send this to BugsHunter?

"Ameer Hussein" <Am...@Ajyal.Com> wrote in message
news:d41d3ab4.04032...@posting.google.com...

Ameer Hussein

unread,
Mar 30, 2004, 4:24:13 PM3/30/04
to
Yes I did. I also found another issue related to the same function in
support.cavo.com. I guess we'll have to wait for 2717.

Robert Pope

unread,
Apr 6, 2017, 2:49:05 AM4/6/17
to
Bumping this thread because it was useful in identifying an issue in our app. We were getting FIELDPUT (occasionally 5333) errors on a very basic loop, the code was essentially as follows:

LOCAL oServer AS DBServer

DO WHILE .NOT. oServer:EoF
oServer:FIELD := 0 // 30 more lines like this, all setting zero to a float
oServer:Skip()
END DO
oServer:Commit()

This was the most common error:

***********************ERROR********************************
Visual Objects (Version 2.8. Build 3.2838), Version 2.8 SP4b
2017-04-06 15:40:51
Application: ...

Error message:
--------------
Error Code: 30 [ OPERATION NOT SUPPORTED ]
Subsystem: BASE
Operation: <=, Arg: 0, Type: LONGINT
Function: FIELDPUT
Argument: 17
Type: LONGINT
Argument Number: 2
Requested type: UNKNOWN
CallStack:
MYDBFSERVER:FIELDPUT (Line:33) (This calls DBServer:FIELDPUT)
MYTABLE:DAY:ASSIGN (Line:2)

Error Object created:
--------------------
SubSystem :BASE
SubCode :0
GenCode :Operation not supported
OsCode :0
ArgType :LONGINT
FuncPtr :0x0002EE5E
ArgNum :2
FuncSym :FIELDPUT
Severity :0
CanDefault :.F.
CanRetry :.F.
CanSubstitute :.T.
Operation :<=, Arg: 0, Type: LONGINT
Description :
FileName :
Tries :0
FileHandle :0
SubCodeText :
Arg : 17
ArgTypeReq :UNKNOWN
MaxSize :0
SubstituteType :LOGIC
CallFuncSym :
--------------------

Reading through other threads, we put DynLock() and DynUnlock() around the loop, which stopped the error was but wasn't a practical solution.

Putting a CollectForced() prior to the Skip() caused the app to crash on the first loop.

We had the following two lines in our FUNCTION Start(). This was also a console app - which is something in common with the parent. Commenting out those two lines made the error disappear. Even if I keep the CollectForced() in the loop, it still works as expected.

// SetMaxDynSize(128*1024*1024) // 128 MB
// DynSize(200)


Otto Christiaanse

unread,
Apr 6, 2017, 8:30:13 AM4/6/17
to
On Thursday, April 6, 2017 at 8:49:05 AM UTC+2, Robert Pope wrote:
> On Tuesday, March 30, 2004 at 5:59:10 AM UTC+11, Ameer Hussein wrote:

I wonder which other errors you got.

You could start with putting the '30 more lines like this' in a seperate method. That way, on the return, the GC can try to cleanup the dynmen.
Remember: there are also other registers that can get to small.

Robert has a nice routine to check and (if necessary) upgrade these registers.

I put that routine in a little class, that can be used in a timer window or called whenever you want.

However, I'm just a bit in doubt whether 5333 is really triggered by dynmem related problems, or that there is some other culprit.

Maybe the other errors show more details.

Regards,
Otto

Jamal

unread,
Apr 6, 2017, 10:49:06 AM4/6/17
to
Robert,

I see you are skipping in the loop.

Try adding the following around the loop to avoid the extra overhead when
updating the dbServer.
This also avoids issues if a primary index key is updated, because record
pointers may change and the skip operation may not be on the correct row
(record).

oServer:SuspendNotification()

// your fieldput loop

oServer:ResetNotification


HTH,
Jamal

"Robert Pope" wrote in message
news:f05a8991-18c1-4143...@googlegroups.com...

Robert Pope

unread,
Apr 7, 2017, 4:48:51 AM4/7/17
to
I had a look into this again today. I was a bit misleading with the 5333 error. They did appear, but only when the crash occurred on an oServer:RecNo debug call that I added as part of debugging, which I omitted it from my sample.

The loop was modified in the following way to receive that error:

LOCAL oServer AS DBServer

DO WHILE .NOT. oServer:EoF
OutputDebugString(String2PSZ(NTrim(oServer:RecNo))) // 5333 here
oServer:FIELD := 0 // 30 more lines like this, all setting zero to a float
oServer:Skip()
CollectForced() // Running the garbage collector would trigger the problem immediately, rather than after processing ~1000 records.
END DO
oServer:Commit()

If I bring in the SDK code the actual crash is on ACCESS RecNo CLASS DbServer call to VODBRecno().

This was the error. I've replaced company specific stuff with ...

***********************ERROR********************************
Visual Objects (Version 2.8. Build 3.2838), Version 2.8 SP4b
2017-04-07 18:14:04
Application: ...

Error message:
--------------
Error Code: 50 [ ACCESS VIOLATION ]
Subsystem: VO-CODE
Error Subcode: 5333
Function: RECNO
Argument Number: 2
Description: Application Code Error causing Access Violation
CallStack:
REBUILD...HISTORY:REBUILDYTDMTD_GROUP (Line:22)
REBUILD...HISTORY:PROCESS (Line:17)

Error Object created:
--------------------
SubSystem :VO-CODE
SubCode :5333
GenCode :Access Violation
ExceptionCode :C0000005
ExceptionFlags :00000000
ExceptionAddress:1004E188
ParamNumber :2
ExceptionInfo :00000059
Severity :2
CanDefault :.F.
CanRetry :.F.
CanSubstitute :.F.
Operation :
Description :Application Code Error causing Access Violation
FileName :
Tries :0
FileHandle :0
SubCodeText :
Arg :
ArgTypeReq :NIL
MaxSize :0
SubstituteType :NIL
CallFuncSym :
--------------------


One of our other devs worked overnight trying to figure out what caused this crash. We had another server elsewhere in the code that had been closed and was probably pending cleanup by the garbage collector. It seems the cleanup of that object may have been spilling over into this one somehow.

The two servers are completely unrelated. We open, use and close the first, then much later down the line we open and use the server where the garbage collection issue occurs. Our solution for now was to run CollectForced() once we have finished using the first server, which allows us to retain the SetMaxDynSize / DynSize calls.

I have no idea why removing the calls to SetMaxDynSize() and DynSize() preventing these error from occurring, but they did. This wasn't the solution that we ended up using, however.

Cheers!

Robert Pope

unread,
Apr 7, 2017, 4:52:40 AM4/7/17
to
I didn't know using Suspend / Reset notification would have that effect on the primary key update. That would actually be quite a neat feature. I'll have to keep it in mind for future. Thanks.

Otto Christiaanse

unread,
Apr 10, 2017, 9:23:29 AM4/10/17
to
I don't use dbserver, so I can't help you there.

I do know from experience that a higher dynsize allows the GC to wait longer before doing its magic.
However, the GC doesn't check all registers to see if it any is reaching a limit.
I had to deal with this problem too, resulting in sudden crashes without a clear cause.

Glad to hear you circumvented / fixed it somehow.

Regards,
Otto

Marc Verkade

unread,
Apr 10, 2017, 3:32:13 PM4/10/17
to
Hai,
I had this trouble too and have tested numerous configs...
Eventually the defaults work for most of our installations
Regards, Marc

DO CASE
CASE Instr("/MEMMODELOLD",Upper(AsString(_GetCmdLine())))
sGeheugen:=Universe:IniFileMain:GetSetString("AlgemeneInstellingen","MaxDynSpaceOldModel","16000000")
SetMaxDynSize(Val(sGeheugen))
sGeheugen:=Universe:IniFileMain:GetSetString("AlgemeneInstellingen","DynSizeOldMOdel","120")
DynSize(Val(sGeheugen))
CASE Instr("/MEMMODELHALF",Upper(AsString(_GetCmdLine())))
sGeheugen:=Universe:IniFileMain:GetSetString("AlgemeneInstellingen","MaxDynSpaceHalf","24000000")
SetMaxDynSize(Val(sGeheugen))
sGeheugen:=Universe:IniFileMain:GetSetString("AlgemeneInstellingen","MaxThreadDynSpaceHalf","24000000")
SetMaxThreadDynSize(Val(sGeheugen))
sGeheugen:=Universe:IniFileMain:GetSetString("AlgemeneInstellingen","DynSizeHalf","180")
DynSize(Val(sGeheugen))
CASE Instr("/MEMMODELPLAZA",Upper(AsString(_GetCmdLine())))
sGeheugen:=Universe:IniFileMain:GetSetString("AlgemeneInstellingen","MaxDynSpacePlaza","33554432")
SetMaxDynSize(Val(sGeheugen))
sGeheugen:=Universe:IniFileMain:GetSetString("AlgemeneInstellingen","MaxThreadDynSpacePlaza","33554432")
SetMaxThreadDynSize(Val(sGeheugen))
sGeheugen:=Universe:IniFileMain:GetSetString("AlgemeneInstellingen","DynSizePlaza","250")
DynSize(Val(sGeheugen))
CASE Instr("/MEMMODELROBERT",Upper(AsString(_GetCmdLine())))
sGeheugen:=Universe:IniFileMain:GetSetString("AlgemeneInstellingen","DynSizeRobert","200")
SetMaxDynSize( (Val(sGeheugen)+1)*2^16 )
DynSize (Val(sGeheugen))
CASE Instr("/MEMMODELGEOFF",Upper(AsString(_GetCmdLine())))
SetMaxDynSize( 0x4000000) // 64MB dynamic RAM instead of 16MB
DynSize(200) // increase the initial GC allocation to
12MB
CASE Instr("/MEMMODELDICK",Upper(AsString(_GetCmdLine())))
SetMaxDynSize( 0x8000000)
DynSize(512)
OTHERWISE
// Default
// Always works for Specsplaza, but somehow the autoplanning can fail!
sGeheugen:=Universe:IniFileMain:GetSetString("AlgemeneInstellingen","MaxDynSpace","33554432")
SetMaxDynSize(Val(sGeheugen))
sGeheugen:=Universe:IniFileMain:GetSetString("AlgemeneInstellingen","MaxThreadDynSpace","33554432")
SetMaxThreadDynSize(Val(sGeheugen))
sGeheugen:=Universe:IniFileMain:GetSetString("AlgemeneInstellingen","DynSize","250")
DynSize(Val(sGeheugen))
END

"Robert Pope" schreef in bericht
news:f05a8991-18c1-4143...@googlegroups.com...
0 new messages