{"record":{"id":"d51d003df276c260","repo":"microsoft/FASTER","slug":"physical-pointer-returned-by-allocator-de-reference-pointer","errorCode":null,"errorMessage":"Physical pointer returned by allocator: de-reference pointer to get records instead of calling Get","messagePattern":"Physical pointer returned by allocator: de-reference pointer to get records instead of calling Get","errorType":"exception","errorClass":"FasterException","httpStatus":null,"severity":"error","filePath":"cs/src/core/Allocator/MallocFixedPageSize.cs","lineNumber":174,"sourceCode":"        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public long GetPhysicalAddress(long logicalAddress)\n        {\n            Debug.Assert(isPinned, \"GetPhysicalAddress requires pinning\");\n            if (ReturnPhysicalAddress)\n                return logicalAddress;\n            return (long)pointers[logicalAddress >> PageSizeBits] + (logicalAddress & PageSizeMask) * RecordSize;\n        }\n\n        /// <summary>\n        /// Get object\n        /// </summary>\n        /// <param name=\"index\">The index of the allocation. For BulkAllocate, this may be a value within the chunk size, to reference that particular record.</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public ref T Get(long index)\n        {\n            if (ReturnPhysicalAddress)\n                throw new FasterException(\"Physical pointer returned by allocator: de-reference pointer to get records instead of calling Get\");\n            Debug.Assert(index != kInvalidAllocationIndex, \"Invalid allocation index\");\n            return ref values[index >> PageSizeBits][index & PageSizeMask];\n        }\n\n        /// <summary>\n        /// Set object\n        /// </summary>\n        /// <param name=\"index\"></param>\n        /// <param name=\"value\"></param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long index, ref T value)\n        {\n            if (ReturnPhysicalAddress)\n                throw new FasterException(\"Physical pointer returned by allocator: de-reference pointer to set records instead of calling Set (otherwise, set ForceUnpinnedAllocation to true)\");\n            Debug.Assert(index != kInvalidAllocationIndex, \"Invalid allocation index\");\n            values[index >> PageSizeBits][index & PageSizeMask] = value;\n        }\n","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/microsoft/FASTER/blob/321d872eabda6a0345c8bd76419f89723ed864ae/cs/src/core/Allocator/MallocFixedPageSize.cs#L156-L192","documentation":"MallocFixedPageSize can be configured (ReturnPhysicalAddress) to hand out raw physical pointers for high-performance access. When that mode is on, calling Get(long index) would bypass the pointer indirection the allocator expects, so the method deliberately throws FasterException. Callers must instead de-reference the physical address (GetPhysicalAddress) to obtain a ref T.","triggerScenarios":"Calling allocator.Get(index) on a MallocFixedPageSize instance constructed with ReturnPhysicalAddress = true; typically from helper code like valueRef paths or generic code that assumes object-mode allocators.","commonSituations":"Users switching allocator configuration to physical-address mode for performance and reusing existing Get()-based access code; shared utility functions written against object-mode allocators run against physical-address allocators.","solutions":["Replace Get(index) with GetPhysicalAddress(index) and de-reference: ref var record = ref *(T*)allocator.GetPhysicalAddress(index)","Set ForceUnpinnedAllocation / construct MallocFixedPageSize with ReturnPhysicalAddress = false if you need Get/Set object access","Branch on allocator mode in shared code: use physical dereference when ReturnPhysicalAddress is true, else Get()"],"exampleFix":"// before\nref T record = ref allocator.Get(index);\n// after\nif (allocator.ReturnPhysicalAddress)\n{\n    ref T record = ref Unsafe.As<T, T>(ref *(T*)allocator.GetPhysicalAddress(index));\n}\nelse\n{\n    ref T record = ref allocator.Get(index);\n}","handlingStrategy":"type-guard","validationCode":"// Check allocator mode before choosing access pattern\nif (allocator.ReturnPhysicalAddress)\n    ref var r = ref *(T*)allocator.GetPhysicalAddress(index);\nelse\n    ref var r = ref allocator.Get(index);","typeGuard":"static bool UsesPhysicalAddress(MallocFixedPageSize<T> a) => a.ReturnPhysicalAddress;","tryCatchPattern":"try\n{\n    ref var record = ref allocator.Get(index);\n}\ncatch (FasterException ex) when (ex.Message.Contains(\"Physical pointer returned by allocator\"))\n{\n    ref var record = ref Unsafe.AsRef<T>((void*)allocator.GetPhysicalAddress(index));\n}","preventionTips":["Know your allocator mode: ReturnPhysicalAddress=true means all access via GetPhysicalAddress dereference","Write allocator-agnostic helpers that branch on ReturnPhysicalAddress","Set ForceUnpinnedAllocation=true only if you understand pinning semantics","Keep object-mode access code out of physical-address hot paths"],"tags":["faster","allocator","pointer-access","misconfiguration"],"backgroundTag":"invalid-state-transition","analyzedSha":"321d872eabda6a0345c8bd76419f89723ed864ae","analyzedAt":"2026-09-15T22:18:00.693Z","contentChangedAt":"2026-09-15T22:18:00.693Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}