Qbasicnews.com

Full Version: Memory
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
I'm having a problem with running out of string space after I DIM a string. I can only seem to get less than 2000 strings. I think this has to do with the amount of memory allocated to Qbasic by windows. I've tried to right click and change the memory on the properties menu but am somewhat confused about all the different memory types (i.e. Conventional, Expanded, Extended, MS-Dos protected mode).

-Kevin
Every new string that you write in BASIC, QBasic, QuickBASIC, etc., uses up valuable memory, and the strings just keep on piling up, using up more and more memory.

One of the methods used to avoid this problem is to define a fixed length string, then to use this same space over and over, by using the MID$ statement. For instance, you can:
Code:
DIM A AS STRING * 80 'A will have a length of 80 characters, and will have a fixed position in memory.

'use A's space in memory for the first string, using the MID$ statement:
MID$(A,1) = "Hi, there, this is a good way to save memory!"
PRINT A
'continue to use this value of A until a new string is required:

'new string required, so, clean out the current string A:
MID$(A,1) = STRING$(80," ")

'and now, enter the new string in A:
MID$(A,1) ="O.K., now that we know how to use the MID$ statement, we can save space"
PRINT A

'flush out A:
MID$(A,1) = STRING$(80," ")

'enter the new string in A:
MID$(A,1) = " by using the same space in memory that we alloted to the string A."
PRINT A
Running the above program will print:

Hi, there, this is a good response.
O.K., now that we know how to use the MID$ statemente, we can save space by
using the same space in memory that we alloted to the string A.

And only 80 bytes of memory will have been used to store the three strings.

Where this technique really shines is when we use a long iterative method, such as in a sorting routine, and we use MID$ to use the same space in memory over and over.
How does this differ from:

[syntax="qbasic"]
'$DYNAMIC
CLS
PRINT "Hi, there, this is a good way to save memory!"
PRINT "O.K., now that we know how to use the MID$ statement, we can save space"
PRINT "by using the same space in memory that we alloted to the string A."
[/syntax]

or

[syntax="qbasic"]
'$DYNAMIC
CLS
a$ = "Hi, there, this is a good way to save memory!"
PRINT a$
a$ = "O.K., now that we know how to use the MID$ statement, we can save space"
PRINT a$
a$ = "by using the same space in memory that we alloted to the string A."
PRINT a$
[/syntax]

or even

[syntax="qbasic"]
'$DYNAMIC
DIM a AS STRING * 80
CLS
a = "Hi, there, this is a good way to save memory!"
PRINT a
a = "O.K., now that we know how to use the MID$ statement, we can save space"
PRINT a
a = "by using the same space in memory that we alloted to the string A."
PRINT a
[/syntax]

I think using MID$ is unnecessary.

*peace*

Meg.
Meg: I really do believe that you are a guru, wandering or not! You've got me! I am not familiar at all with the '$DYNAMIC that precedes your three examples. I ran into something like that previously in some code posted here. I copied it to my QuickBASIC 4.5 and tried to run it; it kept giving me an error about a metacommand. I posted my problem, asking why QB didn't see the single quote as a remark, but had no answer on that. Now, your first example runs fine on my QB, but, I have no idea what the '$DYNAMIC does.

The whole thing boils down to what I could see in the old BASIC that I used on my Tandy-Radio Shack Color Computer, somewher in the early 1980's. I knew then how to display the program after it ran, so that one could see that common strings where simply added at the end, one on top of the other. They were referred to as "garbage", and many a "garbage collector" scheme was devised to eliminate the buildup and loss of available memory. However, if one defined the length of a string, then BASIC had no problem rewriting to the same address, as long as the string did not exceed the stated length and, if I remember correctly, one used the MID$ statement. After all, the original poster's problem was

"Tue Jan 18, 2005 7:57 am Post subject: Memory
--------------------------------------------------------------------------------
I'm having a problem with running out of string space after I DIM a string."

Perhaps you can tell him how to solve his problem?

In your first and second examples, I don't understand how your initial '$DYNAMIC can prevent the strings from piling up, as in "the good old days" of BASIC.

In your third example, I'm not sure how, having declared a length for the string a, the rest of the program cleans out the previous value of a, and prints only the new string...but I would love to know more! If inapropriate to continue here, perhaps you could send me a PM?
Well, I don't even think that's necessary, either. I believe that all strings in QB behave in this way, as long as you use the same variable name. For example:

[syntax="qbasic"]
CLS
PRINT "FREE SPACE: ", FRE(0), FRE(-1)
a$ = "abcdefghijklm"
PRINT "FREE SPACE: ", FRE(0), FRE(-1)
a$ = "a"
PRINT "FREE SPACE: ", FRE(0), FRE(-1)
a$ = "abcdefghijklmnopqrstuvwxyz"
PRINT "FREE SPACE: ", FRE(0), FRE(-1)
DO: LOOP UNTIL INKEY$ <> ""
SYSTEM
[/syntax]

Notice that the free space goes UP when you shorten the string length. As long as you keep using the same a$, it will not be eating up your string space.

You'll notice the same thing with printing constant strings:

[syntax="qbasic"]
PRINT "FREE SPACE: ", FRE(0), FRE(-1)
PRINT "Hello, world!"
PRINT "FREE SPACE: ", FRE(0), FRE(-1)
[/syntax]

Notice no change in free space. So really, no need to write to a string--then print it--at all. It's not saving you anything.

What used to happen to me a lot (before I started modularizing my big programs) was that the compiler would run out of space while trying to prep constant-string heavy games I was making. I moved a lot of the text to external files, and that solved most of the problems that modularizing didn't fix.

*peace*

Meg.
Meg: I tried your examples, and noted what you said, that the use of the same string seems to automatically wipe out the old value and substitute it with the new value, with use of memory limited to the requirements of the new value. Hmm, quite different from the old BASIC! I even did a "DIM L(100) AS STRING*100, and the reported memory was not changed at all! (Perhaps the array is located outside of the memory reported by FRE()?).

And, what are metacommands?
Taken from QBOHO:

Code:
$STATIC and $DYNAMIC Metacommand Details  
  
The $STATIC and $DYNAMIC metacommands tell the compiler how to allocate  
memory for arrays. Neither of these metacommands takes an argument:  
  
  'Make all arrays dynamic.  
  '$DYNAMIC  
  
$STATIC sets aside storage for arrays during compilation. When the  
$STATIC metacommand is used, the ERASE statement reinitializes all array  
values to zero (numeric arrays) or the null string (string arrays)  
but does not remove the array. The REDIM statement has no effect  
on $STATIC arrays.  
  
$DYNAMIC allocates storage for arrays while the program is running.  
This means that the ERASE statement removes the array and frees  
the memory it took for other uses. You can also use the REDIM statement  
to change the size of a $DYNAMIC array.  
  
The $STATIC and $DYNAMIC metacommands affect all arrays except implicitly  
dimensioned arrays (arrays not declared in a DIM statement). Implicitly  
dimensioned arrays are always allocated as if $STATIC had been used.

This example shows the use of ERASE with the $DYNAMIC and $STATIC  
metacommands:  
  
REM $DYNAMIC  
DIM A(100, 100)  
'This deallocates array A.  
ERASE A  
'Redimension array A.  
REDIM A(5, 5)  
  
REM $STATIC  
DIM B(50, 50)  
'This sets all elements of B equal to zero.  
'B still has the dimensions assigned by DIM.  
ERASE B

You won't see a change in your FRE() unless you either $DYNAMIC or use REDIM instead of DIM. The memory for your DIM array gets allocated during compilation by default. Almost as if all your DIM statements get chunked out of memory before the program starts running.

If you use $DYNAMIC, the memory will not be allocated until the actual DIM command is encountered while going through the code.

*peace*

Meg.
Meg: Thanks. That explains a lot! Big Grin
Thanks for the help. I assume from your answers that there is no way to increase the amount of RAM available to qb.exe and the best approach is to conserve memory using your helpful suggestions.

From what I have been able find on the web, this has to do with the limited ability of this DOS program to only load in the limited conventional memory. Is this correct?

thanks again for the help,

Kevin
You could try out libraries which give you access to EMS/XMS memory. You can store strings in XMS Smile
Pages: 1 2