I like to use interactive debuggers like gdb (for C) or pdb (for python) for that.
You first have to localize a region (function) you want to study, then you reach one of its execution with a breakpoint, or a conditional breakpoint.
Then, you inspect:
- the callstack: in which condition the function was call
- the parameters / local variables
- the subfunctions: in both tools, you can manually call any (reachable) function, try different parameter values and check the result. Pay attention through to the side effects!