WinFakt! - (7763 of 826982 - 1%) 

 Home | Tips & Tricks | General Info | Downloads | NG Archive | Links | Email | Search | Register | Users | Login

 


 

Tips & Tricks

 

Rating: 45% (4 votes registred)
Rate this item:

Back to list

A guide to the 322 and 5333 error in Clipper

Getting rid of the 322/5333 error with Clipper & Fivewin

Here I’ll explain how I got rid of the dreaded 322 and 5333 Clipper errors with FiveWin apps.  What I’ll present here is product of comments and fragments of codes of different FiveWin users, as well as mine.

This doesn’t pretend to be a technical explanation as of why it happens, nor if the use of Memory(-1) is good or evil.  This is what’s worked for me for over a year an a half (with some new things thrown in along the way) with the final result of no more reports from users (or in my own PC) of the 322 or 5333 Clipper errors.  Tested both, Clipper 5.2e and 5.3e, plus FiveWin 2.1c, I’m sure it applies just as well to any version of FiveWin 2.0 or higher.

To see why the calls to Memory(-1), make sure you app has a message bar object and double click on it to see FiveWin reporting the memory usage (FW 2.1 and above).  You’ll see that the value returned by MemUsed() goes down much more when Memory(-1) is used.  Also notice how high MemMax() gets.  My experienced showed me that when it reached 16,000,000 the app just died; using Memory(-1) as shown below helped keep MemMax() at bay.  Please feel free to comment out the use of Memory(-1) to see the difference by yourself.

Credits here go to Peter Kohler, Alex Isamat and myself.  If I omit someone, please let me know and forgive my forgetfulness.

Also, some users haven’t seemed to ever experience these errors, while others have with different impact.  So if you haven’t run across this error, I would suggest no to touch anything: if it ain’t broke, don’t fix it.

 

Disclaimer: If this doesn’t work for you or if you PC starts a fires, I cannot be held liable.  This is free advice and code sharing with no responsibility on my part.

Luis Krause

November 11, 2002

 

 

1.- Adjust your link script file like this:

 

BLINKER INCREMENTAL OFF

BLINKER EXECUTABLE COMPRESS 1           # use ONLY with Blinker 5.x and above

BLINKER CLIPPER SYMBOL ON

 

File YourMainPrg

File MoreSourceCode

 

# Blinker 5.0 and above file to replace module in Clipper.Lib

File MPar

 

# The following files ONLY if you use Clipper 5.2e

# These were extracted from Clipper.Lib from Clipper 5.3b

# You must own Clipper 5.3b; I won’t provide you with these modules

File Alloc, OM, Memory

 

Lib OtherLIbsYouMightBeUsing

 

PACKCODE

PACKDATA

 

DEFBEGIN

   name        AppName

   description 'The Best Thing Around Town'

   exetype     Windows 3.1

   code        preload moveable discardable

   data        preload moveable

   rc          YourResFile.res  // instead of external YourResFile.dll - mutually exclusive!

   stacksize   16500                             // this figure depends on your app

   heapsize    5120                              // this figure depends on your app

   segment     'PLANKTON_TEXT' nondiscardable

   segment     'EXTEND_TEXT'   nondiscardable

   //segment     'OM_TEXT'       nondiscardable  // because of OM.OBJ call above

   segment     'OSMEM_TEXT'    nondiscardable

   segment     'SORTOF_TEXT'   nondiscardable

   segment     'STACK_TEXT'    nondiscardable

DEFEND

 

Library Five, FiveC, Objects, WinApi

Library Clipper, Extend, Terminal

 

 

2.- Adjust your YourMainPrg.prg file:

 

#include “FiveWin.ch”

 

Static oWnd, oGarbage

 

Function Main()

 

Define Window oWnd ;

   Title “Test App” ;

   Menu BuildMenu() ;

   MDI

 

Define Message Bar Of oWnd Keyboard Date Clock

 

// more of you stuff

 

Activate Window oWnd ;

   On Init InitApp()

 

Return Nil

 

//---------------------------------------------

 

Static Function BuildMenu()

Local oMenu

// here goes you menu

Return oMenu

 

//---------------------------------------------

 

Static Function InitApp()

 

SetHandleCount( 180 )  // or whatever suits you

 

// Define and start the Timer that controls the Garbage Collector

oGarbage := TTimer():New( 60000, ;

   {|| SysRefresh(), ;

       If( MemMax() > 15000000 .and. MemUsed() > 15000000, ;

         ( oGarbage:DeActivate(), ;

           MsgAlert( "Memory resources running low" + CRLF + ;

                           "Please restart the program ASAP", “Your App” ), ;

           oGarbage:Activate() ), ;

         ( Memory(-1), Memory(-1), Memory(-1), Memory(-1), Memory(-1) ) ) }, oWnd )

Eval( oGarbage:bAction )                    // start our own "garbage collector"

oGarbage:Activate()

 

Return Nil

 

//---------------------------------------------

 

Exit Function EndApp()

 

If oGarbage # Nil

   oGarbage:end()

Endif

 

Return Nil

//---------------------------------------------

 

 

3.- Modify TDialog Class, ::Initate() method:

 

METHOD Initiate( hWndFocus, hWnd ) CLASS Tdialog

 

// current code

 

   #ifdef __CLIPPER__

      Memory(-1)                   // Add this line

      ASend( ::aControls, "Initiate", ::hWnd )

   #else

      ASend( ::aControls, "Initiate()", ::hWnd )

   #endif

 

// current code

 

Return lFocus              // .t. for default focus

 

 

4.- Modify TMDIChild Class, ::End() method (code has been optimized from original):

 

METHOD End() CLASS TMdiChild

 

   Local lEnd := ::lValid()

 

   If lEnd

      if ::oMenu != nil .and. ! ::lKeepMenu

         ::oMenu:End()

      endif

      ::oWndClient:ChildClose( Self )

      SetIdleAction( {|| KillMemHog() } )   // free memory hogged by FW's MDI'S

   Endif

 

Return lEnd

 

// add this new static function at the end of mdichild.prg

 

//----------------------------------------------------------------------------//

// Helper function adapted from Peter Kohler's idea

Static Function KillMemHog()

/*

  clean up memory after MDI windows close.

  This seems to work quite well to force Clipper to clean up memory after

  you close a  MDI dialog/Window: You can't call

  memory(-1) directly at the end of your MDI window as the window is still

  open using the memory you want to release,

  so you have to call it somehow a few seconds after your MDI window closes.

  Must be a function, not a method, which would keep the object in memory.

*/

 

Static nSeconds := 0

Local  nCount   := 0

 

If nSeconds == 0

   nSeconds := Seconds()

Endif

 

If Seconds() - nSeconds > 2

   // Clear idle action

   SetIdleAction()

   nSeconds := 0

 

   For nCount := 1 To 16    // feel free to adjust this to suit your needs

      Memory(-1)

   Next

 

Endif

 

Return Nil

 

 

 

So that’s it.  Make those changes to both, your code and the mentioned FiveWin classes and you should see the dreaded 322 & 5333 errors go away, just like I did.

 

 

 

 

© 2002 Bekz.net, Inc. All Rights Reserved.