Exercise 44.1.
Suppose 𝜎,ℎ ⊧𝑃 ∗(𝑄 ∨𝑅). Choose ℎ =ℎ1 ⊎ℎ2 with 𝑃 on ℎ1 and 𝑄 ∨𝑅 on ℎ2. If the left disjunct holds on ℎ2, the same split witnesses 𝑃 ∗𝑄; otherwise it witnesses 𝑃 ∗𝑅. Thus the right-hand disjunction holds. Conversely, a witness split for either 𝑃 ∗𝑄 or 𝑃 ∗𝑅 is also a split for 𝑃 ∗(𝑄 ∨𝑅) after the corresponding disjunction introduction.
No state satisfies 𝑃 ∗𝖿𝖺𝗅𝗌𝖾: its defining split would require one component to satisfy 𝖿𝖺𝗅𝗌𝖾. Hence 𝑃 ∗𝖿𝖺𝗅𝗌𝖾 ⊧𝖿𝖺𝗅𝗌𝖾. The converse entailment is vacuous because 𝖿𝖺𝗅𝗌𝖾 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 ℓ =𝜎(𝑥) =𝜎(𝑦). The separating conjuncts would require a split ℎ =ℎ1 ⊎ℎ2 with ℎ1={ℓ↦1},ℎ2={ℓ↦2}. Their domains both contain ℓ, contradicting the disjointness required for ⊎. Hence the antecedent has no model and entails 𝖿𝖺𝗅𝗌𝖾.
For the ordinary conjunction, take a store with 𝜎(𝑥) =𝜎(𝑦) =ℓ and the singleton heap ℎ ={ℓ ↦1}. Both exact points-to assertions inspect the same whole heap, so 𝜎,ℎ ⊧𝑥 =𝑦 ∧𝑥 ↦1 ∧𝑦 ↦1. The assertion 𝑥 ↦1 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 ℓ =[[𝐸]]𝜎. For safety monotonicity, suppose 𝖿𝗋𝖾𝖾(𝐸) is safe on (𝜎,ℎ0) and ℎ0#𝑟. Safety gives ℓ ∈dom(ℎ0), hence also ℓ ∈dom(ℎ0 ⊎𝑟); rule E-Free therefore applies to the larger heap.
For factorization, a large execution has result 𝐻=(ℎ0⊎𝑟)↾(dom(ℎ0⊎𝑟)∖{ℓ}). Disjointness gives ℓ ∉dom(𝑟). Put ℎ′0 =ℎ0 ↾(dom(ℎ0) ∖{ℓ}). The small execution is ⟨𝖿𝗋𝖾𝖾(𝐸),𝜎,ℎ0⟩⇓⟨𝜎,ℎ′0⟩, and the domains calculate as dom(ℎ′0)=dom(ℎ0)∖{ℓ},dom(𝐻)=(dom(ℎ0)∖{ℓ})∪dom(𝑟). Consequently ℎ′0#𝑟 and 𝐻 =ℎ′0 ⊎𝑟, which are exactly the two conclusions of the factorization clause.
Exercise 44.3.
Deleting the side condition would let us frame 𝑅:=𝑥 =1 around {𝗍𝗋𝗎𝖾} 𝑥:=0 {𝑥=0} and derive {𝗍𝗋𝗎𝖾∗(𝑥=1)} 𝑥:=0 {(𝑥=0)∗(𝑥=1)}. Take 𝜎(𝑥) =1 and ℎ =∅. Splitting the empty heap into two empty heaps shows that the precondition holds. Execution produces the store 𝜎′ =𝜎[𝑥 ↦0]. The postcondition would require both 𝜎′(𝑥) =0 and 𝜎′(𝑥) =1, so it is false. In the proof of theorem 44.13, the invalid step is the appeal to lemma 44.8 to conclude 𝜎′,𝑟 ⊧𝑅: here 𝑥 ∈mod(𝑥 :=0) ∩fv(𝑅).
Exercise 44.5.
The small-footprint axiom is H-Store: ⊢{𝐸↦−} [𝐸]:=𝐹 {𝐸↦𝐹}. Frame 𝑅:=𝑧 ↦7. The command modifies no store variable, so mod([𝐸] :=𝐹) =∅ and therefore mod([𝐸]:=𝐹)∩fv(𝑅)=∅. Rule H-Frame gives exactly ⊢{𝐸↦−∗𝑧↦7} [𝐸]:=𝐹 {𝐸↦𝐹∗𝑧↦7}. 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 𝑥 ↦𝑎 ∧𝑦 ↦𝑏. Because points-to is exact, its first conjunct forces the whole heap to be {𝜎(𝑥) ↦[[𝑎]]𝜎} and its second forces the same whole heap to be {𝜎(𝑦) ↦[[𝑏]]𝜎}. It is satisfiable exactly when the two singleton maps are equal, hence when 𝜎(𝑥)=𝜎(𝑦)≠𝗇𝗎𝗅𝗅and[[𝑎]]𝜎=[[𝑏]]𝜎. It never describes two distinct cells, so it cannot replace the starred precondition of proposition 44.17.
For an inexact global predicate, 𝑥 ↦𝑎 would merely assert that the heap contains the indicated entry. Two such conjuncts can then hold in a larger heap, but when 𝑎 =𝑏 they can also both name the same cell. The swap proof would therefore need the explicit premise 𝑥 ≠𝑦; the separating conjunction obtains that fact from disjointness instead.
Exercise 44.7.
Choose the temporary 𝑧 distinct from 𝑥, as required by proposition 44.21. Instantiate that proposition first at 𝑛 +1 and then at 𝑛: ⊢{𝖼𝗁𝖺𝗂𝗇𝑛+2(𝑥)} 𝗉𝗈𝗉 {𝖼𝗁𝖺𝗂𝗇𝑛+1(𝑥)},⊢{𝖼𝗁𝖺𝗂𝗇𝑛+1(𝑥)} 𝗉𝗈𝗉 {𝖼𝗁𝖺𝗂𝗇𝑛(𝑥)}. One use of H-Seq yields ⊢{𝖼𝗁𝖺𝗂𝗇𝑛+2(𝑥)} 𝗉𝗈𝗉;𝗉𝗈𝗉 {𝖼𝗁𝖺𝗂𝗇𝑛(𝑥)}. The smallest admissible value is 𝑛 =0: the input then has exactly two cells and the result has length zero, namely an empty heap with 𝑥 =𝗇𝗎𝗅𝗅.
Exercise 44.8.
Choose the outer separating split ℎ =ℎ1 ⊎ℎ2 with 𝖼𝗁𝖺𝗂𝗇𝑛(𝑥) on ℎ1 and 𝖼𝗁𝖺𝗂𝗇𝑚(𝑦) on ℎ2. By lemma 44.19, |dom(ℎ1)| =𝑛 and |dom(ℎ2)| =𝑚. The domains are disjoint, so finite-set cardinality gives |dom(ℎ)|=|dom(ℎ1)|+|dom(ℎ2)|=𝑛+𝑚. If 𝑛,𝑚 >0, the same lemma puts 𝜎(𝑥) in the first domain and 𝜎(𝑦) in the second. Disjointness of those domains therefore implies 𝜎(𝑥) ≠𝜎(𝑦). 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 𝑃 made the displayed sequence safe, and choose 𝜎,ℎ ⊧𝑃. Put ℓ =𝜎(𝑥). Safety of the first command requires ℓ ∈dom(ℎ), and E-Free produces ℎ′ =ℎ ↾(dom(ℎ) ∖{ℓ}). The store is unchanged, so the following load again asks for address ℓ. But ℓ ∉dom(ℎ′); no load rule applies and the sequence faults. This contradicts validity of a Hoare triple with precondition 𝑃.
Proof-theoretically, H-Free consumes the small-footprint premise 𝑥 ↦ − and returns 𝖾𝗆𝗉 on that footprint. The second premise of H-Seq would have to establish the points-to precondition 𝑥 ↦𝐹 required by H-Load; neither 𝖾𝗆𝗉 nor a frame disjoint from the freed cell can entail it. An intervening allocation can repair the derivation by executing 𝑥 :=𝖺𝗅𝗅𝗈𝖼(𝑣), which changes 𝑥 to a freshly chosen location and establishes a new assertion 𝑥 ↦𝑣 before the load. Nondeterministic freshness does not promise reuse of the old location; safety follows because the program follows the new value of 𝑥.
Exercise 44.10.
Rule H-Alloc gives ⊢{𝖾𝗆𝗉} 𝑥:=𝖺𝗅𝗅𝗈𝖼(0) {𝑥↦0}. The postcondition entails 𝗍𝗋𝗎𝖾, so consequence gives the same command the postcondition 𝗍𝗋𝗎𝖾. Rule H-Assign, instantiated with the postcondition 𝗍𝗋𝗎𝖾, gives ⊢{𝗍𝗋𝗎𝖾} 𝑥:=𝗇𝗎𝗅𝗅 {𝗍𝗋𝗎𝖾}. Sequence therefore derives ⊢{𝖾𝗆𝗉} 𝑥:=𝖺𝗅𝗅𝗈𝖼(0);𝑥:=𝗇𝗎𝗅𝗅 {𝗍𝗋𝗎𝖾}. This does not contradict proposition 44.22: the program does not fault, and 𝗍𝗋𝗎𝖾 intentionally forgets the final heap.
A postcondition that exposes the leak is ∃ℓ. 𝑥=𝗇𝗎𝗅𝗅∧ℓ↦0. The existential remembers that the final heap is exactly one allocated cell, while the only command-visible root 𝑥 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 𝖼𝗁𝖺𝗂𝗇𝑛+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.