12

Is there a tool that automatically "marks" some functions so that I can get an approximation of a "call stack".

Actually, I would like to have a behavior similar to the one you get by writing fct = Debug.trace "fct" $ ... without having to add it before each function.

I know that profiling does something similar with -fprof-auto, but I need it to be displayed while the application is running.

Some time, I have infinite loops and having this display could show me immediately which function(s) is faulty. Using hlist and breakpoints isn't really helpfull since you already have to know the name of one of the functions in the cycle.

2
  • 1
    Do you know the "probabilistic debugging" technique? You start your program running, and at any point you choose, break out into the debugger. You are now probably in the function that takes the most time to compute (since the probability that you stop in any given function is related to how much time is spent in that function!). Commented Sep 3, 2013 at 15:53
  • Yep, that's what is recommended by the documentation of the GHCi debugger (you should first set -fbreak-on-exception). But as far as I recall, it doesn't worked well the last time I used it, and I really had to add before each call the function name to figure out what was happening. Commented Sep 5, 2013 at 21:47

2 Answers 2

13

Here is something incredibly ugly ;-), and it only gives you the line number instead of the function name, but I was surprised to find out that it works, so I thought I'd share it. And it's still better than nothing. You can use the C preprocessor just like in good old C days:

{-# LANGUAGE CPP #-}

#define traceLoc trace (__FILE__ ++":"++ show __LINE__)

import Debug.Trace

f 0 = traceLoc $ 1
f n = traceLoc $ g (n-1)
g 0 = traceLoc $ 2
g n = traceLoc $ 2 * f (n-1)    

Now,

*Main> f 3
Test.hs:16
Test.hs:18
Test.hs:16
Test.hs:17
4
Sign up to request clarification or add additional context in comments.

4 Comments

what kind of CPP is that: __FILE__ ++":"++ show __LINE__ ;-) but it is so cool!
@SassaNF That is haskell with the CPP macros for the file name and line number. CPP is just a macro system, no reason to require the macros to result in any particular language.
It's prettier that way, although if you have hundreds of functions, it's still a pain :(
Just curious: if you are using Debug.Trace anyway, why not just use its trace function? Seems to be exactly what @Jeremy needs.
1

I have developed a plugin for GHC 9+ which does just the thing, but not for every function call instead it prints something like CFG to a file named run.out

Here is the link:

https://github.com/moxeed/bug-riper/blob/master/plugin/Instrumentation.hs

Unfortunately, it's not a package and you have to add it manually to your code by fplugin flag in GHC:

common instrumentation
    ghc-options: -fwrite-ide-info
                 -hiedir=.hie
                 -Wall 
                 --fhpc
                 -fplugin=Instrumentation
    build-depends: plugin-lib

By Adding -O0 flag when building your code, it will actually print for every call. just remember to remove it after debugging is finished.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.