Delphi Rio安卓64位应用External exception XX问题排查咨询
Having dealt with similar Delphi Android 64-bit issues before, let's break down what these External exception XX errors mean and how to troubleshoot them—especially since you're seeing them across all devices and can't replicate the problem locally.
External exception XX Errors These aren't standard Delphi exceptions—they're wrappers for Android native signals that the Delphi runtime converts into exception objects. For context on common codes you're seeing:
External exception B0typically maps toSIGBUS(bus error, often from misaligned memory access or invalid memory addresses)External exception 87usually corresponds toSIGFPE(floating-point exception, e.g., division by zero or invalid floating-point calculations)External exception 90is oftenSIGABRT(abort signal triggered by native code assertions or low-level crashes)
The fact they're popping up in "safe" FMX code like ArrangeControl or TRectF.Offset is a critical clue: the actual root cause is likely memory corruption or invalid state introduced earlier in your code, which only manifests later when FMX tries to perform routine operations.
Based on your call stack (triggered via FormKeyUp → ShowPreviousFrame → Realign → ArrangeControl) and cross-device occurrence, here are the most probable culprits:
- Memory corruption: Wild pointers, out-of-bounds array access, or freeing objects while they're still referenced can corrupt the heap or stack. This corruption might not trigger an error immediately—it lays in wait until FMX code accesses the damaged memory.
- Thread safety violations: If background threads modify FMX controls or UI-related data without proper synchronization (using
TThread.Synchronize/TThread.Queue), they can leave controls in an invalid state. When the UI thread tries to realign controls (like inShowPreviousFrame), this invalid state causes a native signal. - FMX control lifecycle bugs: Examples include accessing a frame/control after it's been destroyed, or calling
EndUpdate/Realignon a form that's in the process of being disposed. - Delphi Rio Android 64-bit compiler bugs: Rio (10.3) had several known issues with Android 64-bit, including memory alignment problems in FMX controls and JNI interaction bugs.
- Third-party component/library issues: Non-standard Delphi components or native Android libraries (via JNI) might not be properly adapted for 64-bit, leading to memory errors.
Since you can't replicate locally, focus on logging, memory debugging, and incremental isolation:
1. Enhance Error Context Logging
Your existing exception reporter captures the stack, but you need more context to pinpoint the root cause:
- Add logs before/after
ShowFrameandShowPreviousFramethat record:- The frame being shown/hidden (class name, memory address, and
ComponentState) - Form bounds and alignment properties (e.g.,
Self.BoundsRect,Alignvalues of child controls) - Thread ID of the executing code (to catch unexpected background thread access)
- The frame being shown/hidden (class name, memory address, and
- Modify
GlobalGetExceptionStackInfoto log additional details like the contents of theTRectFbeing passed toArrangeControl(if possible) and any recent UI operations.
2. Enable Memory Debugging Tools
- Use Android's AddressSanitizer (ASAN): Compile your app with ASAN enabled (in Delphi's project options under Linking → Advanced → Additional linker flags, add
-fsanitize=address). ASAN will catch memory leaks, out-of-bounds access, and use-after-free errors in native code, pointing you directly to the source of corruption. - Leverage Delphi's memory checks: Enable
FastMM4(or the built-in memory manager's debug mode) to detect invalid memory operations. While FastMM's Android 64-bit support is limited, it can still catch some Delphi-level memory issues.
3. Audit Thread Safety
- Verify all UI-related operations (frame creation/destruction, form updates, control property changes) run on the main UI thread. Any background thread modifying UI state must use
TThread.SynchronizeorTThread.Queue. - Check if
ShowPreviousFrameorShowFrameis ever called indirectly from a background thread (your call stack shows it's triggered byFormKeyUp(UI thread), but hidden indirect calls could exist).
4. Isolate the Problem Code
- Simplify frame transitions: Temporarily disable the
TShowFrameTransitionanimation inShowFrameto rule out animation-related state corruption. - Remove third-party components: Gradually disable or remove non-core third-party components (especially those handling UI or memory) and monitor if exceptions stop occurring.
- Test with a minimal reproducible case: Create a stripped-down version of your app that only includes the
MainForm, frame navigation, and key handling. If the exception still occurs, you can narrow down the issue faster.
5. Check Control Lifecycle Management
- Add logs to your frame's
OnCreateandOnDestroyevents to ensure frames are properly created and disposed. Look for cases where a frame is destroyed but still referenced in yourMainForm. - Verify that
EndUpdateis always paired withBeginUpdateon your form—unbalanced calls can leave the form in an invalid state that triggers realignment errors.
6. Update Delphi or Apply Patches
Delphi Rio had several critical fixes for Android 64-bit in subsequent patches (e.g., 10.3.3). If you're not running the latest patch for Rio, apply it. Alternatively, test your app in a newer Delphi version (like 10.4 Sydney or 11 Alexandria) to see if the issue is resolved—Embarcadero fixed many FMX memory and alignment bugs in later releases.
内容的提问来源于stack exchange,提问作者zeus

