Trap in MAU
Trap in MAU
What does "Trap @00001630H in MAU, Line: 26, Code: 11" mean?
-
- Site Admin
- Posts: 525
- Joined: Fri Dec 31, 2010 12:30 pm
- Contact:
Re: Trap in MAU
The identification of the error codes are in Section 8.1 Runtime Error Codes in the Oberon for Microcontrollers document. Trap 11 is a heap overflow.
If you suspect you are not always going to have enough free memory on your MCU when using NEW to allocate heap space you should use the MAU functions HeapUsed or MemAvailable to keep track of your usage.
If you suspect you are not always going to have enough free memory on your MCU when using NEW to allocate heap space you should use the MAU functions HeapUsed or MemAvailable to keep track of your usage.
-
- Posts: 8
- Joined: Tue Sep 06, 2011 3:53 pm
- Location: Russia
Re: Trap in MAU
Thanks! I have been solved my problem. The NEW() should not be called in WHILE TRUE DO ... END; loop to prevent heap overflow. It should be put in PROCEDURE to memory be cleaned right way! I tested this in V4.01 of Astrobe.
Right way (do not led to heap overflow):
Wrong way (led to heap overflow):
BUT am I understand right, that then NEW called previous ARRAY should be removed from the memory? why it is not removed? Is it a bug or the rule?
Right way (do not led to heap overflow):
Code: Select all
MODULE MauV4;
IMPORT Out, MAU, Main;
PROCEDURE Test;
VAR p: ARRAY OF INTEGER;
BEGIN
NEW(p, 4);
Out.String("proc "); Out.Int(MAU.MemAvailable(), 6); Out.Ln;
END Test;
PROCEDURE Run;
BEGIN
WHILE MAU.MemAvailable() > 10 DO
Out.String("while "); Out.Int(MAU.MemAvailable(), 6); Out.Ln;
Test
END;
END Run;
BEGIN
Run
END MauV4.
Code: Select all
MODULE MauV4;
IMPORT Out, MAU, Main;
PROCEDURE Run;
VAR p: ARRAY OF INTEGER;
BEGIN
WHILE MAU.MemAvailable() > 10 DO
Out.String("free "); Out.Int(MAU.MemAvailable(), 6); Out.Ln;
NEW(p, 4);
END;
END Run;
BEGIN
Run
END MauV4.
-
- Site Admin
- Posts: 525
- Joined: Fri Dec 31, 2010 12:30 pm
- Contact:
Re: Trap in MAU
NEW only ever allocates memory - it never frees any memory. When you use NEW on a local dynamic array as in your example the memory is allocated on the stack (not the heap), just like the memory used by other local variables. When you exit from the procedure the memory used by the dynamic array is returned to the system.
If you allocate an array more than once, e.g.
it would not cause an error but is no more useful than declaring two arrays e.g.
and never using one of them.
Note that as p is an ARRAY OF INTEGER in your example, NEW(p, 4) allocates enough memory for 4 INTEGERs, i.e. 16 bytes. If you really want to test that you have enough memory you should write:
If you allocate an array more than once, e.g.
Code: Select all
NEW(p, 4);
NEW(p, 4);
Code: Select all
VAR
a, b: ARRAY 4 OF INTEGER;
Note that as p is an ARRAY OF INTEGER in your example, NEW(p, 4) allocates enough memory for 4 INTEGERs, i.e. 16 bytes. If you really want to test that you have enough memory you should write:
Code: Select all
IF MAU.MemAvailable() >= 16 THEN
NEW(p, 4)
END;
-
- Posts: 8
- Joined: Tue Sep 06, 2011 3:53 pm
- Location: Russia
Re: Trap in MAU
I can not understand how to free memory from new elements. I make the example to demonstrate the problem.
I made a chain of data structures received form PC, and then processing them one by one. But cant find the way how to free unused chain elements.
Help me please.
I had been test it on a Astrobe V3.4 Starter and Astrobe V4.0.2 Evolution.
I made a chain of data structures received form PC, and then processing them one by one. But cant find the way how to free unused chain elements.
Help me please.
Code: Select all
MODULE MauV4;
IMPORT Out, Main, MAU;
TYPE
Event = POINTER TO RECORD
next: Event
END;
VAR
v: Event;
PROCEDURE Add;
VAR item: Event;
BEGIN
IF v = NIL THEN
NEW(v);
v.next := NIL
ELSE
item := v;
WHILE item.next # NIL DO
item := item.next
END;
NEW(item.next);
item.next.next := NIL
END
END Add;
PROCEDURE Clear;
BEGIN
(* Do some work here *)
(* How to free memory from a chain unused tail ??? *)
v := NIL;
v.next := NIL;
END Clear;
PROCEDURE Run;
BEGIN
v := NIL;
v.next := NIL;
WHILE TRUE DO
Out.String("Available: "); Out.Int(MAU.MemAvailable(), 5); Out.Ln;
Add;
Clear
END
END Run;
BEGIN
Run
END MauV4.
-
- Site Admin
- Posts: 525
- Joined: Fri Dec 31, 2010 12:30 pm
- Contact:
Re: Trap in MAU
Astrobe has a built-in function called DISPOSE which is complementary to NEW. You can use DISPOSE to possibly deallocate dynamic memory for subsequent reuse. This was mentioned in a previous post in this forum:
NEW / DISPOSE and Memory Allocation
Alternatively, if you have a situation where a list of pointers is continually growing and shrinking then you could implement a system which maintains a separate list of the freed pointers. Then, when you need to to use an additional pointer of the same type you can take it from the freed list. You would only need to use NEW to allocate another pointer when the freed list is empty. The total amount of memory used is then limited to the maximum number of pointers that are in use at any one time.
NEW / DISPOSE and Memory Allocation
Alternatively, if you have a situation where a list of pointers is continually growing and shrinking then you could implement a system which maintains a separate list of the freed pointers. Then, when you need to to use an additional pointer of the same type you can take it from the freed list. You would only need to use NEW to allocate another pointer when the freed list is empty. The total amount of memory used is then limited to the maximum number of pointers that are in use at any one time.
Last edited by cfbsoftware on Sun Jul 28, 2013 10:29 pm, edited 1 time in total.
Reason: Updated for the latest version of Astrobe
Reason: Updated for the latest version of Astrobe
-
- Posts: 8
- Joined: Tue Sep 06, 2011 3:53 pm
- Location: Russia
Re: Trap in MAU
Thanks for the answer and advice! I made a solution by making fixed circular list of pointers. Maybe somebody find it useful in same cases as mine.
Code: Select all
MODULE MauV4;
IMPORT Out, Main, MAU, Random;
TYPE
Event = POINTER TO RECORD
data: INTEGER;
next: Event
END;
VAR
list , r, w: Event;
PROCEDURE InitList;
VAR item: Event; i: INTEGER;
BEGIN
NEW(list );
item := list ;
FOR i := 1 TO 20 DO
NEW(item.next);
item := item.next
END;
item.next := list;
r := list;
w := list;
END InitList;
PROCEDURE Add(VAR a: INTEGER): BOOLEAN;
VAR item: Event; res: BOOLEAN;
BEGIN
(* If were any place in list *)
IF w.next # r THEN
w.data := a;
(* Make a step in the cycle *)
w := w.next;
res := TRUE
ELSE
res := FALSE
END;
RETURN res
END Add;
PROCEDURE Do(): BOOLEAN;
VAR res: BOOLEAN;
BEGIN
(* If something is written in the list *)
IF r # w THEN
(* Do processing of data *)
Out.String("data: "); Out.Int(r.data, 7); Out.String("mem free: "); Out.Int(MAU.MemAvailable(), 4); Out.Ln;
(* Make a step in the cycle *)
r := r.next;
res := TRUE
ELSE
res := FALSE
END
RETURN res
END Do;
PROCEDURE Run;
VAR rand, counter: INTEGER;
BEGIN
InitList; (* Init circular list *)
counter := 1;
WHILE TRUE DO
(* Irregular addition of data to list *)
rand := Random.Next(1000);
IF rand > 500 THEN
IF Add(counter) THEN
INC(counter)
ELSE
Out.String("LIST IS FULL"); Out.Ln
END
END;
(* Irregular data processing *)
rand := Random.Next(1000);
IF rand > 500 THEN
IF ~ Do() THEN
Out.String("LIST IS EMPTY"); Out.Ln
END
END
END
END Run;
BEGIN
Run
END MauV4.