Programming & Compilers
How memory mapped file truncation separates address and backing validity
Memory mapped file truncation can leave an address mapped but without backing. Trace file extents, reader lifetimes and retained immutable versions.

A reader maps a file, checks its length, and keeps the mapping open. Another process shortens the file. The reader's address range can remain mapped while a later access reaches an offset whose backing bytes no longer exist under the selected mapping contract. Keeping the mapping alive has preserved an address relationship; it has not necessarily preserved the file's original extent.
The failure behind memory mapped file truncation is a mismatch between two lifetimes. The reader wants the bytes it accepted at startup to remain readable until its work ends. The operating system's mapping API may provide no such promise against another participant changing the same backing object. A sound design must coordinate that mutation or give the reader an immutable version with a sufficient lifetime.
Draw the mapped interval and the backing file extent separately
The Linux manual illustrates why this requires a declared contract. It says a file descriptor can be closed after mmap returns without invalidating the mapping. Its SIGBUS entry covers an attempted access to a page beyond the mapped file's end. In NOTES, however, it says that the effect of changing the underlying file's size on pages corresponding to added or removed regions is unspecified. MAP_PRIVATE likewise leaves visibility of subsequent file changes unspecified. The numeric history below is therefore an explicit model of removed backing, not a claim that these manual entries guarantee one exact result for every concurrent truncation.
Use a stipulated model with 4096-byte pages. A file object O initially contains 12288 bytes, and a reader maps its entire interval beginning at file offset zero. If the mapping starts at virtual address V, it covers addresses from V through V + 12287. The initial file offsets are the half-open interval [0, 12288). Three complete pages provide the initial backing.
The model requires a file-backed access to refer to bytes within O's current extent. If truncation removes an entire backing page, the model rejects a subsequent access to that page. A real test must establish the selected platform's reporting behavior separately. The model intentionally avoids partial final pages, whose behavior may have additional rules. It also avoids assigning one universal signal, exception, or return code to all systems.
Before any change, an access at offset 9000 lies within both the mapping and the backing file extent. Its virtual address is V + 9000, and the file has that offset. An access at offset 13000 lies outside the mapping as well as outside the initial file. These cases already show two separate predicates: whether the virtual address belongs to the mapping and whether the selected backing object supplies the requested offset.
Now shorten O to 8192 bytes. The remaining file interval is [0, 8192), but stipulate that the mapping descriptor still covers [V, V + 12288). Offset 9000 remains inside the originally mapped address range. It is outside the file's new extent, so the model rejects the backing access. Offset 8191 remains backed; offset 8192 is the first removed byte. Mapping presence and valid backing disagree for the entire last page.
Trace mapping lifetime through a concurrent shortening
The reader first opens O, records its length, and establishes its mapping. It then validates a structure located in the third page. A writer subsequently truncates that same object to two pages. Finally, the reader follows an offset to another field in the third page. No explicit unmap is needed for this sequence to violate the reader's assumption about available backing.
The startup length check was accurate when performed. It does not protect later accesses from mutation between that check and use. Repeating the length check immediately before a load still leaves an interval in which a writer can shorten O. The application needs a protocol that stabilizes the object for the whole required read interval, or a method whose documented semantics supply the needed independent data.
An open handle can identify O consistently without freezing its contents or size. Another handle to the same object can perform the truncation. Similarly, keeping the mapping descriptor alive can preserve mapping lifetime while leaving the backing extent mutable. These identities are useful for tracing which object changed, but their mere existence is not an exclusion mechanism.
The runtime code replacement guide makes a useful comparison for mapping lifetime. Publishing a new entry does not end the lifetime of old frames and retained callbacks; their old version needs its own retirement boundary. A mapped file reader has a comparable retention obligation when new readers discover a replacement version. The mechanisms differ: retained code references do not establish a file-mapping API's rules, and a private mapping does not itself certify that every original file offset survives shortening.
Keep cached residency separate from valid access
The reader may already have touched offset 9000 before truncation. That observation establishes that the old access succeeded; it does not establish that a later access is permitted. A resident page, a cached copy of file data, and an address translation are implementation state. Their existence cannot replace the documented contract for accessing an object whose extent has changed.
In the stipulated model, the removed third page cannot be treated as valid backing merely because its bytes were previously fetched. A platform may invalidate translations or change page state during truncation. Other systems may impose different restrictions or failure behavior. Check the chosen API before treating prior residency as a promise of later access.
A successful repeated read needs interpretation against the declared contract. An experiment may leave a page resident, miss a timing window, or exercise a different mapping mode than production. It can reveal behavior under its recorded conditions. The correctness argument still needs the documented rule and a protocol that covers all admitted writer actions during the reader's interval.
There is also a distinction between shortening and ordinary content mutation. A file can retain its length while a writer changes a header, offsets, or payload bytes. Stabilizing the backing file extent prevents the particular missing-backing problem; it does not automatically provide a consistent document snapshot. If the reader relies on relationships among fields, its protocol must protect those relationships too.
Compare in-place truncation with immutable version publication
Linux truncate and ftruncate set the named or descriptor-referenced regular file to the specified byte length. When the file was larger, the extra data is lost. That documented size change gives the model its new extent of 8192; it does not fill in mmap's unspecified size-change effects. Record which API changed O and which mapping contract applies before interpreting a real load result.
With in-place shortening, O is both the reader's backing object and the writer's mutation target. Safe concurrent use requires an agreement that prevents the relevant mutation while a reader depends on O. One option is a cooperative lock covering the complete read interval. The writer takes the conflicting lock before changing O's size or protected contents, and releases it only after the agreed update is complete.
The coordination identity must remain shared by the reader and writer for every protected access. A lock on an object that the writer replaces may fail to coordinate a later opener of the new object. The structured concurrency guide, linked through backing file extent, gives a related lifetime boundary: actual child settlement matters before resource cleanup, and a timeout or cancellation request alone does not establish that boundary. Here the protected readers must actually finish their dependent mapped accesses before O1 can be shortened or reclaimed. The peer supplies the resource-lifetime comparison, not a file-lock or mapping implementation.
An alternative creates a new immutable version O2 while existing readers continue using O1. After O2 is complete and validated, the writer changes the publication binding so new readers discover O2. In a platform contract where an existing mapping remains associated with its old object, a reader already using O1 does not suddenly acquire O2's bytes because the pathname changed.
This alternative only works if O1 remains suitable backing until its last reader finishes. Publishing O2 must not be followed by truncating O1 to reclaim space while readers still map it. An application needs retention and reclamation rules, such as explicit reader references or another verified lifetime mechanism. File-name replacement alone does not prove that old backing is protected against further mutation.
Namespace removal and object destruction are also different events under many mapping contracts. A version can cease to be discoverable by its former pathname while existing handles still identify it. Whether that guarantees continued mapped access depends on the selected platform and what other actors can do to the object. Verify the required rule instead of equating disappearance from a directory listing with either safe retention or immediate destruction.
Define the reader interval before choosing coordination
The interval begins when the reader obtains the version and validates the assumptions its later loads depend on. It ends only after the final dependent access. A lock acquired for startup validation and released before parsing does not cover the parser's subsequent loads. Nor does a reader reference protect the right version if it is registered after a writer can already reclaim that version.
A version protocol needs an atomic or otherwise coordinated admission step: select O1 and establish the protection that keeps O1 valid before reclamation can pass it. The writer then publishes a different version for new admissions and retires O1 only after its protected readers drain. The exact mechanism is a design choice, but the race between selecting and protecting the old version must be addressed explicitly.
A reader can instead copy required data into independently owned storage under a safe read protocol, then stop relying on the mapping. The copying phase still needs consistent and valid backing while it runs. Once complete, later operations on the copy have a different lifetime dependency. This changes the application's storage and copying costs; it does not make an uncoordinated copy from a changing file automatically safe.
All these protocols assume writers obey the mutation boundary or are prevented from violating it. A separate process with authority to truncate the same object outside the convention can invalidate the safety argument. Advisory coordination among participating processes cannot establish protection against an unregulated writer.
Use a bounded test that exposes the two validity checks
A deterministic model test can represent mapping length and file length as separate integers. Start with both at 12288, then change only file length to 8192. Check offsets 0, 8191, 8192, 9000, and 12288. The first two are inside both intervals, the next two are mapped but unbacked, and the last is outside the mapping. This tests the interval reasoning without claiming to execute an operating-system fault.
An actual platform test should record the API, mapping mode, filesystem, page size, file identity, and synchronization used to guarantee truncation occurs before the tested access. Run fault-producing cases in an isolated test process with an appropriate observation mechanism. Check its actual result against the documented platform rule. Do not publish a successful model calculation as proof that one signal or exception is delivered by every operating system.
A boundary table and its event log can be kept together on the Lenovo IdeaPad 15.6-inch FHD touch laptop. The native catalogue description gives 16GB DDR4, a 512GB PCIe SSD and an i5-1334U processor. Use that workspace to save the original mapping length, the verified file length after shortening, and the exact access offset. A machine's memory capacity cannot turn residency into a contractual guarantee about removed backing.
For comparing the documented API with an isolated test result, the ASUS Vivobook 14-inch FHD laptop provides a listed 14-inch FHD display and Core 5 120U processor. Keep the mapping mode and filesystem identity beside the child process's observed outcome. The model's offset 9000 remains mapped after shortening but falls outside the new extent. A correct memory mapped file truncation protocol prevents that forbidden backing change during a reader's complete interval, or retains an independently suitable version until the reader finishes.