Ada95受控类型引发PROGRAM_ERROR难定位,表达式计算器运行异常求助
Hey there, let's dig into this frustrating exception you're hitting with your expression calculator. That PROGRAM_ERROR pointing to finalize/adjust raised exception is a classic pain point when working with Ada's controlled types, but we can narrow down the causes step by step.
First, let's recap: the error means an exception was thrown during the Adjust (copy-time adjustment) or Finalize (cleanup) phase of a controlled type, and Ada doesn't allow exceptions to escape these procedures—hence the top-level PROGRAM_ERROR. Here are the most likely culprits to check:
Null dereferences in Adjust/Finalize
If your expression nodes use access types (like pointers to sub-expressions), it's easy to accidentally dereference a null pointer in these procedures. For example:- In Adjust, if you're deep-copying a node but forget to initialize a child access component before accessing it.
- In Finalize, if you try to free a child node that was never allocated (left null).
Double-check every access type dereference in both procedures—add null checks if you're unsure.
Shallow copies leading to double-free
If your controlled type manages dynamic memory (like expression tree nodes), a shallow copy (where two controlled objects share the same access type) will cause chaos. When the first object is finalized, it frees the memory; when the second is finalized, it tries to free the same memory again, triggering a memory fault. Make sure your Adjust procedure performs a proper deep copy—allocate new memory for each child node instead of just copying the access value.Uninitialized controlled components
If your controlled type contains other controlled types or components that require explicit initialization, failing to set them up properly can lead to exceptions during Adjust/Finalize. For example, if you have aNodetype with an uninitializedLeft_Childaccess component, Finalize might attempt to finalize that null component (depending on your implementation) and hit an error. Always initialize all components in the type's constructor or Initialize procedure.Uncaught exceptions inside Adjust/Finalize
Ada strictly prohibits exceptions from propagating out of Adjust or Finalize. Even a simpleConstraint_Errorfrom a bad calculation in these procedures will bubble up as a PROGRAM_ERROR. Audit both procedures for any code that could throw an exception—add internal exception handlers if needed, or fix the root cause of the potential error.
Debugging Tips to Pinpoint the Issue
- Crank up runtime checks
Compile your code with GNAT's-gnatEflag to enable extra runtime checks for controlled types, or-gnatd.eto get detailed exception tracebacks that might show exactly which line in Adjust/Finalize is failing. - Add debug print statements
Stick simplePut_Linecalls at the start and end of Adjust/Finalize, e.g.,Put_Line("Finalizing Binary_Node with value" & Node.Value'Image). This will help you see which specific object is triggering the error when the program crashes. - Simplify and isolate
Temporarily strip down your code to test just the controlled type logic: create a single node, copy it, then let it go out of scope. If that triggers the error, you know the problem is in the type's core Adjust/Finalize logic, not the expression parsing code.
内容的提问来源于stack exchange,提问作者Mehdi Saada

