Lectures onType Theory
ch:separation-logic: ch:separation-logic
appendix sectionsolutions

ch:separation-logic: ch:separation-logic

Exercise 44.1.

Suppose σ,hP(QR). Choose h=h1h2 with P on h1 and QR on h2. If the left disjunct holds on h2, the same split witnesses PQ; otherwise it witnesses PR. Thus the right-hand disjunction holds. Conversely, a witness split for either PQ or PR is also a split for P(QR) after the corresponding disjunction introduction.

No state satisfies Pfalse: its defining split would require one component to satisfy false. Hence Pfalsefalse. The converse entailment is vacuous because false has no states. Together these arguments give both requested equivalences without appealing to the main-line separating algebra proposition.

Exercise 44.2.

Assume a state satisfies the antecedent and put =σ(x)=σ(y). The separating conjuncts would require a split h=h1h2 with h1={1},h2={2}. Their domains both contain , contradicting the disjointness required for . Hence the antecedent has no model and entails false.

For the ordinary conjunction, take a store with σ(x)=σ(y)= and the singleton heap h={1}. Both exact points-to assertions inspect the same whole heap, so σ,hx=yx1y1. The assertion x1 already describes ownership of that one-cell heap. Conjoining the same exact assertion under an alias does not create a second ownership claim; separating conjunction is the connective that demands disjoint footprints.

Exercise 44.4.

Write =[[E]]σ. For safety monotonicity, suppose free(E) is safe on (σ,h0) and h0#r. Safety gives dom(h0), hence also dom(h0r); rule E-Free therefore applies to the larger heap.

For factorization, a large execution has result H=(h0r)(dom(h0r){}). Disjointness gives dom(r). Put h0=h0(dom(h0){}). The small execution is free(E),σ,h0σ,h0, and the domains calculate as dom(h0)=dom(h0){},dom(H)=(dom(h0){})dom(r). Consequently h0#r and H=h0r, which are exactly the two conclusions of the factorization clause.

Exercise 44.3.

Deleting the side condition would let us frame R:=x=1 around {true} x:=0 {x=0} and derive {true(x=1)} x:=0 {(x=0)(x=1)}. Take σ(x)=1 and h=. Splitting the empty heap into two empty heaps shows that the precondition holds. Execution produces the store σ=σ[x0]. The postcondition would require both σ(x)=0 and σ(x)=1, so it is false. In the proof of theorem 44.13, the invalid step is the appeal to lemma 44.8 to conclude σ,rR: here xmod(x:=0)fv(R).

Exercise 44.5.

The small-footprint axiom is H-Store: {E} [E]:=F {EF}. Frame R:=z7. The command modifies no store variable, so mod([E]:=F)= and therefore mod([E]:=F)fv(R)=. Rule H-Frame gives exactly {Ez7} [E]:=F {EFz7}. No syntactic freshness hypothesis is needed. The two starred factors in the precondition supply disjoint singleton heaps, and hence distinct addresses; the frame-rule side condition concerns modified store variables only and is automatic because this heap-store command has an empty modified-variable set.

Exercise 44.6.

With ordinary conjunction, the proposed precondition is xayb. Because points-to is exact, its first conjunct forces the whole heap to be {σ(x)[[a]]σ} and its second forces the same whole heap to be {σ(y)[[b]]σ}. It is satisfiable exactly when the two singleton maps are equal, hence when σ(x)=σ(y)nulland[[a]]σ=[[b]]σ. It never describes two distinct cells, so it cannot replace the starred precondition of proposition 44.17.

For an inexact global predicate, xa would merely assert that the heap contains the indicated entry. Two such conjuncts can then hold in a larger heap, but when a=b they can also both name the same cell. The swap proof would therefore need the explicit premise xy; the separating conjunction obtains that fact from disjointness instead.

Exercise 44.7.

Choose the temporary z distinct from x, as required by proposition 44.21. Instantiate that proposition first at n+1 and then at n: {chainn+2(x)} pop {chainn+1(x)},{chainn+1(x)} pop {chainn(x)}. One use of H-Seq yields {chainn+2(x)} pop;pop {chainn(x)}. The smallest admissible value is n=0: the input then has exactly two cells and the result has length zero, namely an empty heap with x=null.

Exercise 44.8.

Choose the outer separating split h=h1h2 with chainn(x) on h1 and chainm(y) on h2. By lemma 44.19, |dom(h1)|=n and |dom(h2)|=m. The domains are disjoint, so finite-set cardinality gives |dom(h)|=|dom(h1)|+|dom(h2)|=n+m. If n,m>0, the same lemma puts σ(x) in the first domain and σ(y) in the second. Disjointness of those domains therefore implies σ(x)σ(y). This last inference is the load-bearing use of the outer star; the two individual chain facts alone do not compare their heads.

Exercise 44.9.

Suppose a satisfiable precondition P made the displayed sequence safe, and choose σ,hP. Put =σ(x). Safety of the first command requires dom(h), and E-Free produces h=h(dom(h){}). The store is unchanged, so the following load again asks for address . But dom(h); no load rule applies and the sequence faults. This contradicts validity of a Hoare triple with precondition P.

Proof-theoretically, H-Free consumes the small-footprint premise x and returns emp on that footprint. The second premise of H-Seq would have to establish the points-to precondition xF required by H-Load; neither emp nor a frame disjoint from the freed cell can entail it. An intervening allocation can repair the derivation by executing x:=alloc(v), which changes x to a freshly chosen location and establishes a new assertion xv before the load. Nondeterministic freshness does not promise reuse of the old location; safety follows because the program follows the new value of x.

Exercise 44.10.

Rule H-Alloc gives {emp} x:=alloc(0) {x0}. The postcondition entails true, so consequence gives the same command the postcondition true. Rule H-Assign, instantiated with the postcondition true, gives {true} x:=null {true}. Sequence therefore derives {emp} x:=alloc(0);x:=null {true}. This does not contradict proposition 44.22: the program does not fault, and true intentionally forgets the final heap.

A postcondition that exposes the leak is . x=null0. The existential remembers that the final heap is exactly one allocated cell, while the only command-visible root x no longer retains its location. Thus the stronger assertion records the unreachable allocation in the stated one-root sublanguage even though the weaker valid triple hides it.

Exercise 44.11.

The comparison is statement by statement. SLF’s triple_conseq_frame combines consequence with an arbitrary separating frame, matching the composition of H-Conseq and H-Frame. Its triple_ref, triple_free, triple_get, and triple_set respectively match the one-cell footprints of H-Alloc, H-Free, H-Load, and H-Store. The exact archived file ranges are recorded in appendix D.

Three signature mismatches prevent literal identification. SLF’s triple is total correctness in an omni-big-step semantics, whereas definition 44.12 is fault freedom plus partial correctness. SLF commands return values in a postcondition family; the book’s load and allocation commands instead update named store variables. Finally, one unfolding of MList separates a record cell containing both data and a tail pointer from the recursive tail, whereas one unfolding of chainn+1 separates a single next-pointer cell from an exact-length tail. The common disjoint head–tail pattern explains the comparison; it does not identify the node layouts.

Consequently the archived declarations are independent comparison evidence. They cannot prove theorem 44.11, theorem 44.16, whose statements refer to the book’s different commands, store updates, and partial-correctness triple.

Search the book

Type to search the local edition.