Scientific programming in Modula-9 — first steps

↖ contents

4 — Memory: pools, slices and strings

Every language answers "who frees this?" somewhere. C answers it in the programmer's head, garbage-collected languages answer it later and invisibly, and M9 answers it in the signature: storage is carved from a named POOL, a pool is freed as one act, and a procedure that keeps memory beyond its own frame takes the pool as a parameter. Measured across this repository's whole library, the rule holds with no exceptions worth naming: *the pool parameter appears exactly when the allocation outlives the call.* A signature with a pool tells you the result lives on and who owns it; a signature without one is a promise that nothing was kept.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
C4Mem.m9

expected output:

all: n=8 mean=5.25 spread=10.50
mid: n=4 mean=5.25 spread=4.50
shifted: n=5 mean=102.25 spread=4.00
pools: carve, use, free as one
30 characters, and every one accounted for

Walk the pieces:

What the checker refuses

The classic C bug in this territory is returning a pointer into a dead stack frame. M9's version is a pointer into a dead POOL — and it does not compile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
X4Escape.m9

the compiler refuses:

24:3 X4Escape.Make: pool-interior pointer escapes its pool: p lives in scratch, which dies with this frame (par 4.3)

The type PTR Point IN scratch names the pool the pointer lives in, so "does this outlive its arena?" is a question the checker can answer — and does, at compile time, with the frame and the pool in the message. The fix is the signature saying where the storage should live instead: give Make a VAR pool : POOL parameter, declare p : PTR Point IN pool, and the same program compiles and runs — the caller now owns the point, exactly as in Describe above. (Try it in the cell: it is a three-line edit. Note the allocation spelling while you are there: NEW (pool, Point), pool first, like every NEW.)

Ownership goes further than this chapter needs — SHARED counted handles and OWN moves appear with the zarr store in chapter 8 — but the rule of thumb carries the whole way: the signature says who owns what, and the checker holds everyone to it.

← Previous: definition and implementation · Next: reading and writing data →