Page 1 of 1

Sigh... "Program-memory overflow"

Posted: Tue Aug 01, 2006 11:29 pm
by Stoves
Attempting to compile a 140k .bas file to .exe stand-alone. Getting the following error:

"BC C:\STUFF\QBASIC\QB45\RPGGEN~1.BAS/E/X/O/T/C:512;
Microsoft (R) QuickBASIC Compiler Version 4.50
(C) Copyright Microsoft Corporation 1982-1988.
All rights reserved.
Simultaneously published in the U.S. and Canada.
001E D97A CASE CHR$(0) + "P"
^ Program-memory overflow

Out of memory

42749 Bytes Available
0 Bytes Free

0 Warning Error(s)
2 Severe Error(s)"

I looked up http://support.microsoft.com/default.as ... n-us;37770. I removed the error handler that used RESUME NEXT, but that didn't solve the problem. Looks like supposedly my only option is to attempt breaking up my code into more SUBS, but I already have 164 SUBS, so I don't see how splitting them into more is necessarily going to fix the problem. Anyone else get an error like this and figure out a way around it?

Posted: Wed Aug 02, 2006 4:52 am
by Z!re
Divide your code into modules, or try using FreeBASIC

Posted: Wed Aug 02, 2006 1:40 pm
by moneo
Stoves,

BC C:\STUFF\QBASIC\QB45\RPGGEN~1.BAS/E/X/O/T/C:512;

On your compile command above:

1) If you removed error handling and resume, then you shouldn't need /E and /X. They add extra memory. Try again without these.

2) The /O will use BRUN45.LIB instead of the standard, default BCOM45.LIB. Assuming you have BCOM45.LIB, remove the /O.

3) I'm not sure what /T does for you, but I've compiled hundreds of programs without it and never had a problem. Try removing it.

4) Remove the /C:512. This is only if you're using an asynchronous communications adapter, for increasing the buffer size from 128 to 512. You don't need this.

If you still have memory problems, take a look at the arrays that you DIMed. Either make them smaller or you might need to use dynamic arrays, in which case you need to add /AH to the BC compile command.

If none of this works, email me the source code (as a .TXT file) to:
EdwardMoneo@gmail.com
so that I can analyse it.

*****

Thanks!

Posted: Thu Aug 03, 2006 10:21 pm
by Stoves
Thanks for the suggestions! Never got it to work in qb4.5, but after a couple hours of cleaning up the code to be compatible with FB, got it working.

Posted: Tue Aug 15, 2006 10:19 pm
by Andi
Z!re wrote:Divide your code into modules, or try using FreeBASIC
I'm having the exact same problem as Stoves is except that I can't seem to get FreeBasic to work for me either.

I don't understand what you mean about dividing your code into modules, is there a good faq on the subject someone could link me to? I only have a limited amount of experience with Qbasic.

Conversion from QB to FB

Posted: Wed Aug 16, 2006 12:19 pm
by Stoves
Conversion from QB to FB

There are enough differences between FB and QB that it could take a good bit of updating before your code will run in FB. I downloaded the FBIde in addition to the FreeBASIC command line compiler which has a nice help module. (http://www.freebasic.net/index.php/deta ... =tool&id=1)


Here's just a few of the things I found out while updating my QB code:

- FB can't read a .bas file from QB unless it has been saved into a text format.

- FB uses CHR$(255) instead of CHR$(0) when comparing inkey$ input.

- All variables should be DIMed in FB.

- Variables are case sensitive in FB.

- Variables should not be named the same as functions or subs in FB to avoid potential conflict. (sometimes gives duplicate definition error)

- Bload syntax is a little different in FB: BLOAD filename$, @pictureArray(0)


Someone should write a tutorial on converting QB programs to FB. (I was thinking about it, but I don't know that I can commit the time yet.)


Splitting program into modules

Use subroutines and/or functions instead of one long continuous main program. For example, you could create a subroutine that centers text in Screen 13 (screen is 80 characters wide). Here's some code that uses one subroutine: (Note that SUBs are DECLARED at the beginning of the program, and the actual code for SUBs are typed after the main program.)

Code: Select all

DECLARE SUB center (lineNumber%, text$)

DIM pause$
pause$ = ""

CLS
SCREEN 13

LOCATE 12
PRINT "I am not a centered line of text."

center 15, "I am a centered line of text."

pause$ = INPUT$(1)

END


SUB center (lineNumber%, text$)

DIM centerPosition%, halfScreenWidth%, halfTextWidth%

'Half of the screen width in Screen 13 is 40 characters.
halfScreenWidth% = 40
halfTextWidth% = INT(LEN(text$)/2)

  centerPosition% = halfScreenWidth% - halfTextWidth%
  LOCATE lineNumber%, centerPosition%
  PRINT text$

END SUB
FUNCTIONS are similar to SUBs, but allow you to return a value. Here's another similar program which also uses a FUNCTION.

Code: Select all

DECLARE SUB center (lineNumber%, text$)
DECLARE FUNCTION getWidth% (text$)

DIM pause$
pause$ = ""

CLS
SCREEN 13

LOCATE 12
PRINT "I am not a centered line of text."

center 15, "I am a centered line of text."

pause$ = INPUT$(1)

END


SUB center (lineNumber%, text$)

DIM centerPosition%, halfScreenWidth%, halfTextWidth%

'Half of the screen width in Screen 13 is 40 characters.
halfScreenWidth% = 40
halfTextWidth% = getTextWidth% (text$)

centerPosition% = halfScreenWidth% - halfTextWidth%
LOCATE lineNumber%, centerPosition%
PRINT text$

END SUB

FUNCTION getWidth% (text$)

getWidth% = INT(LEN(text$)/2)

END FUNCTION
Further Reading

Here's a simple introduction to using a subroutine: http://www.petesqbsite.com/sections/tut ... ohler1.txt

Here's a collection of tutorials entitled Structured Programming on SUB and FUNCTION programming from Pete's site: http://www.petesqbsite.com/sections/tut ... sc.shtml#5

Posted: Wed Aug 16, 2006 12:50 pm
by Andi
Stoves wrote:Splitting program into modules

Use subroutines and/or functions instead of one long continuous main program. For example, you could create a subroutine that centers text in Screen 13 (screen is 80 characters wide). Here's some code that uses one subroutine: (Note that SUBs are DECLARED at the beginning of the program, and the actual code for SUBs are typed after the main program.)
I understand now. I've actually been using subroutines a ton throughout my program which is why I'm now a little stumped as to how to make the code take up less memory.

My main program is like 54kb worth text and then I have about 100 or so little 1kb subroutines. Maybe I'll just have to find a way to tighten up the code as much as possible on my main program? Or is having that many subroutines taking up a too much memory somehow?
Stoves wrote:- Variables should not be named the same as functions or subs in FB to avoid potential conflict. (sometimes gives duplicate definition error)
Ugh. That totally sucks. That alone makes me want to avoid rewriting my code for FB.

Whoops

Posted: Wed Aug 16, 2006 1:43 pm
by Stoves
Andi wrote:
Stoves wrote:- Variables should not be named the same as functions or subs in FB to avoid potential conflict. (sometimes gives duplicate definition error)
Ugh. That totally sucks. That alone makes me want to avoid rewriting my code for FB.
Now that I double-check, I may be mistaken on that one. It's not listed here in FB Differences from QB: http://www.freebasic.net/index.php/about?section=diff. I know you can't DIM keywords as variables, and for some reason, I thought I was having trouble with using variable names with the same name as SUB names, but maybe not. There are definitely additional differences from what's listed in the official "Differences" webpage though.
Andi wrote:
Stoves wrote:Splitting program into modules

Use subroutines and/or functions instead of one long continuous main program. For example, you could create a subroutine that centers text in Screen 13 (screen is 80 characters wide). Here's some code that uses one subroutine: (Note that SUBs are DECLARED at the beginning of the program, and the actual code for SUBs are typed after the main program.)
I understand now. I've actually been using subroutines a ton throughout my program which is why I'm now a little stumped as to how to make the code take up less memory.

My main program is like 54kb worth text and then I have about 100 or so little 1kb subroutines. Maybe I'll just have to find a way to tighten up the code as much as possible on my main program? Or is having that many subroutines taking up a too much memory somehow?
Yeah, I think the coding limit in QB is something like 160k including all code and memory allocated for variables, arrays, etc. Memory management in QB is a bear.

"The only other limit to be aware of is QBASIC's 160K limit on program AND code size. One buffer of sprites (252 sprites) will eat almost 64K, leaving you with less than 100K to put the rest of your code in! QuickBASIC and PowerBASIC users shouldn't have any problem though."
(See http://www.petesqbsite.com/sections/tut ... etput.html)

Freebasic does not have that memory limitation, so it might be worth checking into in a little more depth.

Posted: Wed Aug 16, 2006 3:22 pm
by Anonymous
lol, brian... have you found that leather prada wallet you were lookin for?

Re: Whoops

Posted: Thu Aug 17, 2006 12:38 pm
by Andi
Stoves wrote:"The only other limit to be aware of is QBASIC's 160K limit on program AND code size. One buffer of sprites (252 sprites) will eat almost 64K, leaving you with less than 100K to put the rest of your code in! QuickBASIC and PowerBASIC users shouldn't have any problem though."
(See http://www.petesqbsite.com/sections/tut ... etput.html)

Freebasic does not have that memory limitation, so it might be worth checking into in a little more depth.
So what I can do is get my entire program under 160K? As long as my main code doesn't exceed 64K and my subs don't take the total size over 160K, I'll be alright?

If that's the case, I can just clean up some of my code on the main program. I've got some ideas on how to do that.

Re: Whoops

Posted: Fri Aug 18, 2006 3:28 pm
by Stoves
Andi wrote:
Stoves wrote:"The only other limit to be aware of is QBASIC's 160K limit on program AND code size. One buffer of sprites (252 sprites) will eat almost 64K, leaving you with less than 100K to put the rest of your code in! QuickBASIC and PowerBASIC users shouldn't have any problem though."
(See http://www.petesqbsite.com/sections/tut ... etput.html)

Freebasic does not have that memory limitation, so it might be worth checking into in a little more depth.
So what I can do is get my entire program under 160K? As long as my main code doesn't exceed 64K and my subs don't take the total size over 160K, I'll be alright?

If that's the case, I can just clean up some of my code on the main program. I've got some ideas on how to do that.
I believe you are correct. I think the info below (especially the third quote) will be helpful.
While Quick Basic was a useful language for rapid development, it had some severe limitations:

64K Dgroup limit on variables (this was a problem with DOS compilers which were limited to 640K of addressable RAM). The limit meant that programmers of larger programs had to go to great lengths to keep from overflowing the 64K variable area. Note that part of this area (about 32K) was taken up with internal variables, so that only 32K was useable. The two most useful work arounds were to use a "STRING" file to store variables, loading the variable value only when required, and to use a separate file to declare variables. Dgroup overflow could cause the next problem to surface.
(See http://en.wikipedia.org/wiki/QuickBASIC)
QuickBasic 4.5 is a standalone product, using pretty much the same IDE, but with no memory restrictions (invoke qb.exe with the /ah switch to remove memory restrictions) and the ability to compile to executable.
Supposedly the /ah switch can be used with the compiler to remove memory restrictions, but I've always had problems anyway. (See http://www.everything2.com/index.pl?node_id=996055)


Also, http://support.microsoft.com/default.as ... N-US;58530 has some good info:
There are several things to keep in mind when programming in QuickBasic. Because Basic manages memory for you, you need to understand the limitations of the Basic memory-management system. The most important points for the programmer are the following:

1. Your program receives one 64K code segment for each module that it contains. If the code generated by the compiler for a given module approaches 64K, you must add a new module to your program to continue adding code. The easiest way to determine if you need to add a new module is to look at the .MAP file produced by the linker, LINK.EXE. You will notice at the top of the .MAP file listing that there is a segment with the same name as your module with an _CODE appended, listed under the BC_CODE class. This is the code segment for that module and must be smaller than 64K.

2. Your entire executable program, no matter how many modules it contains, has only one near data segment. All ordinary variables, all variable-length STRINGs, and your stack are located in this segment. The FRE() function can be used to determine if you are close to filling up this segment. The "Out of STRING Space" error indicates that this segment is full.

Usually, the best approach to minimizing your usage of the near data segment is to move as many items as possible out into the far heap. However, the Basic memory management engine allows only certain types of data items to be placed in far memory. These items are DYNAMIC arrays of numeric data or fixed-length STRINGs. Variable-length STRINGs never go in the far heap.

The easiest way to move these items out of the near data segment is to make all arrays DYNAMIC unless there is a specific reason to keep them STATIC. Usually, the program structure shown below is the simplest organization:

Code: Select all

Pseudo Code
-----------
DIM all STATIC arrays first
COMMON statements next
REM $DYNAMIC
DIM all DYNAMIC arrays here,
including the ones placed in COMMON

Also, if practical, use only arrays of fixed-length STRINGs. Remember, arrays of variable-length STRINGs cannot go into the far heap. These techniques will minimize the portion of the near data segment that your program's data requires, leaving more room for conventional variables and variable-length STRINGs. If any of your DYNAMIC arrays must be larger than 64K, you will need to start QuickBasic or compile with the /Ah option.

Posted: Mon Aug 21, 2006 1:11 am
by burger2227
The program seems way too big to run even with a bunch of subs.

You could use CHAIN to hook different parts of the program together.
IE: Change some subs into other BAS files.

NOTE: If you use CHAIN do not add the extension:
CHAIN "Menu" 'NOT CHAIN "Menu.BAS"
CHAIN automatically finds files of it's own kind. Whether it be BAS or EXE
If you don't you will have to change the CHAIN filename before you compile, which is kinda dumb. This way both the BAS and EXE files will find each other if you need to change some code.

IF you want to compile chained BAS files, you will have to use COMMON SHARED variables and include VBRUN45.

Otherwise you will have to have a datafile pass the information needed to make a Stand Alone application. Good luck

I have made programs that actually ran out of string space LOL

Ted

ALSO SCREEN 13 is 40 columns wide folks

Posted: Mon Aug 21, 2006 1:17 am
by burger2227
SCREEN 12 is 80 wide like the default screen.

12 has the best resolution and 30 rows

Ted