Qbasicnews.com

Full Version: How to resolve "Out of String Space" problem?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Does anyone know what is the max of string variables allowed. The following is part of the code. Am i having TOO many string variables (2520+2520+1), TIA.


TYPE recordInfo
date AS STRING * 10
op AS SINGLE
hi AS SINGLE
lo AS SINGLE
CL AS SINGLE
vol AS DOUBLE
test1 AS SINGLE
test2 AS SINGLE
END TYPE


Length=2520

DIM SHARED record AS recordInfo

DIM SHARED nostop$(1 TO Length)
DIM SHARED io$(1 TO Length)
Er...the code runs fine for me.
Zack, that code is a part of a larger program. So obviously with the added instructions he will get an error.

Kc, you are allocating (2520 * 2) * 255 bytes of string data(Theoretically). Which is quite a lot. Try putting a >> '$dynamic << in the begining of your program. It will help.

Also, if it is possible, post your code so we have a better idea of what you are doing.
Thanks BBQ,

I have an idea, but haven't tried it yet. I really don't need to access all the variables at once, the most I need is probably 50 at any one time, so I will try to store all these (2520*2+1) varaiables into a Ramdom Access file, and get what I need as I go along. Hopefully that will free up some space.

kc
Quote:Kc, you are allocating (2520 * 2) * 255 bytes of string data(Theoretically). Which is quite a lot.
Lol, yeah, its like: 1.225MB's

Actually he's allocating 2520+2520+10 bytes of data

Here's a routine for creating huge arrays on disk:
Code:
DEFINT A-Z
'$DYNAMIC
DECLARE FUNCTION ArrGet$ (arr AS STRING, index AS LONG)
DECLARE SUB ArrPut (arr AS STRING, index AS LONG, dat AS STRING)
DECLARE FUNCTION CreateArray$ (slots&, bytes%)
DECLARE SUB EraseArr (arr AS STRING)
DECLARE FUNCTION RHEX$ (Lenght AS INTEGER)

CLS

PRINT "Loading..."
arr$ = CreateArray(5040, 1000)    'create our array (5mb in size)

t! = TIMER                        'start timing
FOR a& = 0 TO 5040
ArrPut arr$, a&, STR$(a&)        'put some data in the array (at every pos)
NEXT
FOR a& = 0 TO 5040
g$ = ArrGet(arr$, a&)            'retreive all data
NEXT
PRINT TIMER - t!                  'display ttal time for put and get


ArrPut arr$, 0, ""                'put a 0 lenght string
PRINT "->"; ArrGet(arr$, 0); "<-" 'retreive it, is it 1000 bytes? no =)

ArrPut arr$, 0, "Testing "        'put a 8 lenght string (note the space)
PRINT "->"; ArrGet(arr$, 0); "<-" 'retreive it, is it 1000 bytes? no =)

'ArrGet only return the number of bytes saved

EraseArr arr$

'Returns the value stored at index
'in array handle arr
'
'By J. Pihl [Z!re | XiberLord]
'
FUNCTION ArrGet$ (arr AS STRING, index AS LONG)
IF LEN(arr) <> 8 THEN EXIT FUNCTION
ff = FREEFILE
OPEN arr + ".Arr" FOR BINARY AS #ff
slots& = CVL(INPUT$(4, #ff))
bytes = CVI(INPUT$(2, #ff))
IF index > slots& THEN CLOSE #ff: EXIT FUNCTION
offs& = index * (bytes + 2) + 7
t$ = "  "
GET #ff, offs&, t$
t$ = SPACE$(CVI(t$))
GET #ff, , t$
CLOSE #ff
ArrGet$ = t$
END FUNCTION

'Stores dat at location index
'in array handle arr
'
'By J. Pihl [Z!re | XiberLord]
'
SUB ArrPut (arr AS STRING, index AS LONG, dat AS STRING)
IF LEN(arr) <> 8 THEN EXIT SUB
ff = FREEFILE
OPEN arr + ".Arr" FOR BINARY AS #ff
slots& = CVL(INPUT$(4, #ff))
bytes = CVI(INPUT$(2, #ff))
IF LEN(dat) > bytes THEN CLOSE #ff: EXIT SUB
IF index > slots& THEN CLOSE #ff: EXIT SUB
offs& = index * (bytes + 2) + 7
t$ = MKI$(LEN(dat)) + dat
PUT #ff, offs&, t$
CLOSE #ff
END SUB

'Creates an array with slots& slots
'and bytes% bytes per slot
'
'Returns the array handle or nothing if error
'
'Do not lose the handle, without it you can't
'access the array, nor remove it.
'
'By J. Pihl [Z!re | XiberLord]
'
FUNCTION CreateArray$ (slots&, bytes%)
IF bytes > 8192 THEN EXIT FUNCTION
IF slots& * bytes >= 8192 * 1024& THEN EXIT FUNCTION
arrn$ = RHEX(8)
ff = FREEFILE
OPEN arrn$ + ".Arr" FOR BINARY AS #ff
t$ = MKL$(slots&) + MKI$(bytes)
PUT #ff, 1, t$
t$ = MKI$(0)
FOR a& = 0 TO slots&
PUT #ff, 7& + (bytes% + 2) * a&, t$
NEXT
CLOSE #ff
CreateArray$ = arrn$
END FUNCTION

'Removes array file by using array handle
'
'By J. Pihl [Z!re | XiberLord]
'
SUB EraseArr (arr AS STRING)
IF arr = "" THEN EXIT SUB
ff = FREEFILE
OPEN arr + ".Arr" FOR OUTPUT AS #ff
CLOSE #ff
KILL arr + ".Arr"
END SUB

'Returns a lenght long hex string
'
'By J. Pihl [Z!re | XiberLord]
'
FUNCTION RHEX$ (Lenght AS INTEGER)
FOR a = 1 TO Lenght
s$ = s$ + HEX$(INT(16 * RND))
NEXT
RHEX$ = s$
END FUNCTION
The biggest thing to remember about strings and QB is that they are located in your local data segment. All data in the data segment (including strings) is limited to 64K (65536 bytes).

The exception to this is fixed-length strings (but then, these aren't really strings anyway but that is a side issue).

Anyway, knowing that *all* your varriables, strings and static arrays are stored in the data segment will help you manage your memory and avoid the "out of string space" error and the dreaded "string space corrupt" 'halt-and-catch-fire' error.

So, you have a few options - cut back on your strings; use a dynamic array of fixed-length strings; use the PDS compiler with the 'far strings' option; or use VBD where strings are always far (there is no way to make them near).

Personally I use the VBD compiler for far strings and a couple other enhancements.
Z!re nice routine.

100, I use the far option in the compiler. We just need to be economical when it comes to string since its the most common datatype.
Well, when your strings are far, who cares? Wink

It would take a lot and I mean a *LOT* of text to use up the entire DGROUP.

It's only when you are dealing with near strings that you have to worry about the size of your strings.

One of the most *stupid* things I see quite commonly is using strings a buffers for what-not. Unless that buffered data happens to be an actual string, create a dynamic array of DOUBLEs.

I repeat using strings for buffers is *stupid* and anyone who does it is an *idiot*. Wink
I meant when using near strings we need to be...