WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Memory and System Resources

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Memory Allocation, StringSpace, and Arrays

Keywords:  Arrays Memory Allocation Multidimensional Arrays  string space stringspace=  maxvars=

Question:

I'm encountering the dreaded "out of stringspace memory". My question is, if I don't drop variable inside of a called .wbc and then return to the caller, am I using up memory space that I can't drop? The help on CALL states they share the same memory space, so I'm assuming that if I keep calling a .wbc and not dropping the variables, I'm eating up stringspace.

I tried using the .INI and registry edit to increase the string space to no avail under Windows 95. Why does the editing of the [stringspace] within the registry under W95 not work? I've also tried adding it to the www?.ini (forgot the specific name) but we still get the error at the EXACT same location! We cranked it up from 32k to 65k but it still bombed.

We are compiling all our .wbts into .wbc, so do we use the www-prod/[stringspace] key then at compile time for the space to increase when we run the .wbcs?

The funny thing is that at one point winbatch was giving us an "unable to allocate memory" at a line in the middle of a

        'if (isdefined(var)) then drop(var)' 
section! We've tracked down just about anything that could take LARGE amounts of memory, but it's not easy without some sort of FreeStringspace function.

With the memory allocation failure: out of memory for strings: Is there a way to avoid this problem on a large script, say by using a call function?

What sort of debugging do you suggest?

Answer:

The CALL function will not affect the string space.

If the Call'ed WBT files are COMPLETELY independent (as in no variables in common) AND you are NEVER NEVER going to compile the script, you can try the CallExt function. If you are going to compile them, use RunWait of the other scripts instead.

Or you can try the Drop function on unneeded large string variables.

In a pinch, you can allocate a large binary buffer and store strings into the binary buffer, which can store different strings at different offsets and use it as sort of an array.

More details on memory allocation debugging below:


3097 Memory Allocation Failure - Out of memory for variables

Older versions of Winbatch (prior to WB 99) can only support around 400 variables. (Winbatch 99 can handle up to almost 1000 variables).

Note that if you are using the Searcher extender, and if you are recursing through numerous directories and saving those as variable names (e.g., dir%num%, where num=980+ dirs), you can use up the last available variable and crash. In this scenario, you might be able to eliminate a lot of code with the new "Shell Operations" extender. It's in the download area.

All variables are one big happy family. Be aware that EACH faked array element (array%xx%) counts as one variable.

A variable allocated in a WBC file can be dropped at the end of the wbc file or anywhere. It's a good idea to use the Drop command to drop variables whenever possible, to conserve memory usage. However that is usually not the problem. The problem usually is that one or two variables are eating up ALL the space. These must be watched carefully.

The following bit of code will also create the Memory Allocation Failure error:

        num=0

        :loop
        num=num+1
        a%num%=num

        goto loop  
One technique - other than re-writing code, if you have the WinBatch script launch another copy of itself (and then the orignal exit). The new copy starts off with a clean slate.

3096 Memory Allocation Failure - Out of memory for strings

How to debug:

It's tricky to debug. Usually you KNOW what your fat variables are. You could write a subroutine that looks like...

:sizechk
Message("varname",strlen(varname))
Message("varname2",strlen(varname2))
etc etc etc
return
and then sprinkle in:
GOSUB SIZECHK
in the code till you spot the big one.

Another possible problem is fragmentation. The string space could get so broken up that you can't allocate any more space.

Question (tread continued):

You mention string space fragmentation. How do we clean it up? We allocate alot of variables (and dialogs), but we drop them as well.

How does one utilize the registry edits to increase stringspace? Do we have to do this on the machine we are going to compile .wbcs on, or do it to each machine we are going to run the .wbc on?

Answer:

It has to be done on each machine you run it on. Although here is some code that can do it automagically for you...

It checks the entries, and it does not like them, changes them and then re-runs the script.

The code is a tad messy as it is designed to work with both 16 and 32 bit interpreted and compiled versions...

And without further ado...

if WinMetrics(-2) == 0 ;16 bit version
val=IniReadpvt("WB16I","StringSpace",32000,"www-prod.ini")
else ;32 bit version
errormode(@OFF)
val=RegQueryValue(@REGMACHINE,"SOFTWARE\Wilson
WindowWare\Settings\WWW-PROD\WB32I[StringSpace]")
ErrorMode(@CANCEL)
endif
if val!=65500
if WinMetrics(-2)==0 ; 16
   IniWritePvt("WB16I","StringSpace",65500,"www-prod.ini")
   IniWritePvt("WBC16I","StringSpace",65500,"www-prod.ini")
else ; 32
   RegSetValue(@REGMACHINE,"SOFTWARE\Wilson WindowWare\Settings\WWW-PROD\WB32I[StringSpace]",65500)
   RegSetValue(@REGMACHINE,"SOFTWARE\Wilson WindowWare\Settings\WWW-PROD\WBC32I[StringSpace]",65500)
endif

moi=strlower(IntControl(1004,0,0,0,0))

if FileExtension(moi)=="exe"
   Run(moi,"")
else
   Run(WinExeName(""),moi)
endif
exit
endif

Question:

We're developing a Winbatch program that reads in a fairly long list of modems and puts them into a tab delimited list. The list is about 15 to 20K. This tab delimited list is them passed as an Itembox to dialog() which enables the user to select a COM port and a modem from the list.

All is fine so far. However, given that NT can support a large number of COM ports, the user may go back into this dialog box several times. Since dialog() overwrites the original variable passed by Itembox with the item(s) the user selected, the variable must be reloaded each time dialog() is called.

The combination of the small stringspace, large list and memory fragmentation causes the "Out of stringspace" error after about 12 calls to this routine.

I've done everything I can think of including bumping stringspace up to 64K, dropping variables, poking the original list of modems into a binary buffer, refreshing the Itembox "var" from the binary buffer right after the call to dialog(), etc. The only thing I haven't done so far is to break the list up into smaller lists and force the user to select from sublists. If anyone has any other ideas, I would be v-e-r-y greatful.

Answer:

You are running into fragmentation of WinBatch string space problems with your extremely large variables.

You already figured out one way to fix it - break up the list into smaller chunks.

Or once thru the script, you can have the script completely re-launch itself for the next one - or if the user goes back to the dialog box.


StringSpace and FileItemize

A common problem is a FileItemize of large network volumes. Our Searcher extender (available from the download area of our web site, under WinBatch Add-Ons) covers this fairly well. If you're running into out of stringspace errors on a FileItemize, then do a FileItemize of a*.*, then b*.* etc. and process the list in 26 chunks.

Or...

Use a DOS command to grab a list of files and then redirect the output to a file and then use the file commands to go through the file line by line.

RunWait("command.com", "/c dir /b > newfilename")

How to Increase StringSpace And Max Variables

Undocumented workaround for WinBatch 2011B or newer:

Maximum number variables can be set using the following registry setting. The limit will apply to both compiled and interpreted scripts. You would need to change the RegSetValue view flag to 64 for the setting to apply 64-bit scripts. The setting does not affect the variable limit in the WinBatch Studio debugger. The maximum recognized limit is 65000.

WBVer = "WB44I" ; This may change with newly formatted versions of WinBatch 
bitness = 32
If WinMetrics(-2)>2 then bitness = 64
strRegMaxVars = "SOFTWARE\Wilson WindowWare\Settings\WWW-PROD\":WBVer:"\[MaxVars]"
nMaxVars = 4000
if nMaxVars<65000 then RegSetValue( @REGMACHINE, strRegMaxVars, nMaxVars, bitness )

To change the string space:

A change can be made to the registry, under the WinBatch/WWW-PROD section, as in the following:

WBVer = "WB44I" ; This may change with newly formatted versions of WinBatch 
; Set the max string space for the version of WinBatch that is running ( 32-bit or 64 bit ) 
; controls which registry view the function uses when accessing the Windows registry.
bitness = 32
If WinMetrics(-2)>2 then bitness = 64
strRegMaxStrSpace = "SOFTWARE\Wilson WindowWare\Settings\WWW-PROD\":WbVer:"\[stringspace]"
nMaxStrSpace = 65535
if nMaxStrSpace<65000 then RegSetValue( @REGMACHINE, strRegMaxStrSpace, nMaxStrSpace, bitness )
The default setting can be restored by deleting the 'MaxVars' value. Also remember that running the above in a script does not increase the limit for the running script. Disclaimer: WWW is NOT responsible for any spontaneous reformatting of system hard drives nor any nuclear power plant meltdowns that may result from the use of the information contained here-in.

In Older WinBatch versions (i.e. 5.1a) :

To change the string space in Win3.1/3.11:

There is an option to set number of variables and amount of string space allocated, in the WWW-PROD.INI in C:\WINDOWS:

  [WBxxx]
  MaxVars = 400
  StringSpace = 32000
The defaults are shown above. The maximum allowable value for 'StringSpace' is 65535.


Article ID:   W13435
Filename:   Memory Allocation StringSpace and Arrays.txt
File Created: 2012:05:22:14:52:56
Last Updated: 2012:05:22:14:52:56