Allocating and freeing memory in BASIC
|
Hello, This may be a question with an obvious answer, sorry if it’s already answered somewhere. In BASIC you can allocate memory by writing something like “DIM ptr% 100”, and I’ve done that a lot in my programs. But I’m not aware of a way to free that memory once it’s been allocated and you don’t need it any longer. Is it possible to do that? If not, is it possible to allocate and free memory by some other method? Perhaps by some specific SYS commands or something. Patrick |
|
Other than it’s plain existence, I know nothing about that module: “SlidingHeap” seems to do what you want: http://www.starfighter.acornarcade.com/mysite/programming.htm |
|
In general, there’s been no way of releasing the memory claimed by a Since BASIC 1.30, used by RISC OS 5, you’ve been able to use If you need to allocate and free blocks of memory a lot, then it’s probably best to use OS_Heap to implement a memory management system. Not sure if there are any tutorials on this – the Wiki docs are quite helpful as a start, it looks like. |
|
Or on an ancient RISC OS pre-v5 a recent BASIC can be soft-loaded. |
|
Hi Patrick, As Chris noted, I would expect the heap API to be useful. I’ve not tried this yet. However, I found this forum thread which describes some things to be aware of: Quote “The code (all in BASIC) uses OS_Heap 0 to initialize the heap, OS_Heap 2 to claim space on the heap, if needed increasing the heap size with OS_Heap 5. Space not needed anymore is released with OS_Heap 3 and when a heap block is released the heap size is shrunk in chunks of pages with OS_Heap 5 (page size in use is read with OS_ReadMemMapInfo) if possible. The basic space for the heap is gotten by changing the WimpSlot of the app if needed.” Here is another useful link with some BASIC code fragments and example files: |
|
This is a topic that has arisen repeatedly from the very early days of RISC OS. The BASIC heap is static and once a claim has been made memory cannot be reclaimed or resized 1. If you want a temporary block of memory there are some ‘tricks’ to use, or there is The legitimate ways to claim resizeable/releasable memory are to use a heap manager. The OS provides OS_Heap, which is fairly straightforward and is used for the Module area, for example. However, it does not have facilities for controlling the memory within which the heap is created. Using BASIC, it is sensible to create such a heap above HIMEM in an extended wimp slot. This has been done several times in various libraries, most of them probably extinct. My own is at: http://www.kappa.me.uk/Libraries/lbHeap041.zip. This library does the things mentioned in the first reference from Anthony above. Apart from OS_Heap, there have been other heap manager modules, but I think the only survivor is SlidingHeaps, mentioned by Holger. This completely controls a heap above HIMEM. It can be more economical with memory than OS_Heap, but requires more programmer input when things get complex. In these days of memory bounty it might not be worth the extra effort. ;-) BASIC V itself needs a way to allow strings to change size, unlike BASIC II, which used fixed buffers. It uses a String Allocation Table (SAT), which keeps a record of string blocks claimed from the BASIC heap which have been released when a string changes size. BASIC re-uses these blocks whenever it can when manipulating strings. It is possible to exploit this for small blocks of memory that can be claimed and released. My own Basalt maintains an OS_Heap heap above HIMEM, and uses it for all sorts of purposes, including resizeable arrays. It also has its own version of 1 Apart from the singular case of string memory released immediately, before any other claims are made. |
|
Yes, this is something I rather miss when going back to BASIC after using C awhile. There’s no UNDIM or REDIM (and if there was, I wonder how many things would break due to addresses of things moving? It’s what rendered *RMTidy useless). |
|
Because Lua was designed for incorporation into C code on any platform with an ANSI C compiler it cannot allow things like references to specific addresses in memory. Garbage collected memory is the norm in Lua; fixed blocks are foreign to it. That is why RiscLua uses a separate module (so that x is the address of the grabbed memory) then that memory can be reclaimed by the Lua garbage collector once you have executed the statement . While riscos.block[x] is non-nil the memory is safe from garbage-collection. That way RiscLua offers the advantages of both kinds of memory allocation.
|
|
That’s not right, is it? C’s I’d expect an
Just a heads up that Sliding Heap does shift other blocks around to compact the heap. It can be a better solution, but mainly for Wimp applications, because you have to keep track of all those moving pointers… Horses for courses. |
|
That is true. It depends upon whether or not you think BASIC should take the lazy approach or if it should manage it’s memory more effectively. ;-) |
|
If it is an OS_Heap heap then nothing would break, because addresses can only move on resizing and a program tracks that naturally. I have been doing that for a couple of decades, and before Basalt. ;-)
Precisely.
At the time BASIC V was written, both memory and speed were still at a premium. The approach might look ‘lazy’ now, but then it was one of the factors in the ‘legendary’ speed of BBC BASIC. ;-) |
|
“Properly” would be like other platforms: static blocks and still returning unused memory to the system for other tasks to use… That’s a wider RISC OS problem, however. Any built-in BASIC commands should use a static heap, as DIM does now. Sliding heaps are good for some applications, but they’re daunting to new users and can make the system useless for many standard data structures. |
|
There are many methods, the OS_Heap-above-HIMEM approach has been discussed above. Here are some other options. If you only need one allocation (as simple file editors often do), then you can stick that above HIMEM and manipulate the slot size directly (which is what the Heap libraries do for you). Wimp_SlotSize is the SWI to use:
If you only have some small allocations (not arbitrary sized files) you may be tempted to get them from (and remember to return them to) the RMA – OS_Module 6&7 is your friend here. This will be generally frowned upon, yet becomes acceptable if you’ve written a module in assembler. I pass no judgement. For larger or more numerous allocations that you don’t want in your application space – perhaps because you want your program to be able to load very large files on RISC OS 3 machines – you can create a Dynamic Area and put a Heap in there. This is such a common requirement that RISC OS 4 supplied ‘Heaped Dynamic Areas’ to make this trivial. Sadly the very little code required has not made its way to RO5 (I don’t think). (This can be retrofitted once I release VectorExtend) Finally, the other way you can manage allocations is to keep track of freed blocks yourself… which is what BASIC does with strings:
(all code untested and likely to cause eyestrain) |
|
Steve Fryatt said
I wrote something that had a standard Heap-above-HIMEM for static allocations, and then a sliding heap above that for file buffers. |
|
Steve advised:
That’s slightly stretching the word possible in this context. However, that’s exactly what I did with that object-oriented BASIC we discussed years ago (with the last slot taking allocations of any size) and also the not-quite-classes context system that allowed multiple standard variables to be grouped into contextual classes, and switched en masse with a CALL, eg:
Easy way of turning a single file editor into MFMV (multi-file, multi-view). |
|
I wrote a module called Cheap (Compact Heap) that did something similar, with a few twiddles like configurable granualarity. As with SlidingHeaps, I gave it up for the simplicity of OS_Heap once memory usage became less critical. |
|
If you accept that you can know the address of the SAT and its structure, it requires only a few calculations in BASIC to exploit it. It can be entirely legal in machine code using the branch routines.
I had that in mind. Basalt offers it as |
|
If you were to say that Basalt had a built in function to solve Fermat’s last theorem I wouldn’t be entirely surprised. |
|
But it does have a built in function for Mandelbrot iteration. ;-) Sophie had one in very early developments of BASIC V, so I included it after the death of Benoit, in tribute to both. |
|
Sliding heaps are good for some applications, but they’re daunting to new users and can make the system useless for many standard data structures. Pretty much exactly what I do in C, using flex for the shifting stuff, fixing it’s base address, and then putting an |
|
Clever. |
|
BLOAT! |