Debugging with emacs+valgrind

Flattr this

The easiest way to debug: valgrind with the most powerful text editor: emacs

Emacs and valgrindA few days ago my office mate told me about the great debugging tool known as valgrind. Before I have been using the great pairing of emacs+gdb to debug segmentation faults and memory leaks... Now I would never use gdb for this. Moreover, I found a way to somewhat use it from within a shell in emacs to allow fast error browsing.
How to use valgrind?
Consider the following C code (where I have omitted the include statements), I'll assume it is in SegFault.c In fact, this code would not yield a segmentation fault as it is, at least without some compilation tweaking.
int main(void){
int i; double *vector1, *vector2;
vector1=(double*)malloc(3*sizeof(double));
vector2=(double*)malloc(4*sizeof(double));
for(i=0;i<3;i++)vector1[i]=sin(i);
for(i=0;i<4;i++)vector2[i]=cos(i);
for(i=0;i<4;i++)printf("sin(%d): %7.7lf cos(%d): %7.7lf\n",i,vector1[i], i, vector2[i]);
free(vector1);
return 0;}
You can see that this code has several errors. First, when allocating vector1 we only ask for 3 doubles, when we really need 4, and we don't free vector2. Although these two errors, the output of the program at least is not segmentation fault. But these kind of errors, when accumulated, lead to pervasive segmentation faults, quite difficult to locate via gdb. The output of the program is:
sin(0): 0.0000000 cos(0): 1.0000000sin(1): 0.8414710 cos(1): 0.5403023sin(2): 0.9092974 cos(2): -0.4161468sin(3): 0.0000000 cos(3): -0.9899925
Valgrind comes to the rescue! First, we need to compile with source flags:
gcc SegFault.c -lm -g -o SegFault.x -Wall
And now execute this via valgrind. Valgrind acts as a virtual processor, thus keeping trace of memory accesses and the like, at a time penalty. You should use it only to find errors, not every time.
valgrind ./SegFault.x
Valgrind's output for this example is
==24585== Memcheck, a memory error detector.
==24585== Copyright (C) 2002-2008, and GNU GPL'd, by Julian Seward et al.
==24585== Using LibVEX rev 1884, a library for dynamic binary translation.
==24585== Copyright (C) 2004-2008, and GNU GPL'd, by OpenWorks LLP.
==24585== Using valgrind-3.4.1-Debian, a dynamic binary instrumentation framework.
==24585== Copyright (C) 2000-2008, and GNU GPL'd, by Julian Seward et al.
==24585== For more details, rerun with: -v
==24585==sin(0): 0.0000000 cos(0): 1.0000000sin(1): 0.8414710 cos(1): 0.5403023sin(2): 0.9092974 cos(2): -0.4161468==24585== Invalid read of size 8
==24585== at 0x8048587: main (SegFault.c:12)
==24585== Address 0x41c9040 is 0 bytes after a block of size 24 alloc'd
==24585== at 0x4026FDE: malloc (vg_replace_malloc.c:207)
==24585== by 0x8048501: main (SegFault.c:8)sin(3): 0.0000000 cos(3): -0.9899925
==24585==
==24585== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 13 from 1)
==24585== malloc/free: in use at exit: 32 bytes in 1 blocks.
==24585== malloc/free: 2 allocs, 1 frees, 56 bytes allocated.
==24585== For counts of detected errors, rerun with: -v
==24585== searching for pointers to 1 not-freed blocks.
==24585== checked 55,932 bytes.
==24585==
==24585== LEAK SUMMARY:
==24585== definitely lost: 32 bytes in 1 blocks.
==24585== possibly lost: 0 bytes in 0 blocks.
==24585== still reachable: 0 bytes in 0 blocks.
==24585== suppressed: 0 bytes in 0 blocks.
==24585== Rerun with --leak-check=full to see details of leaked memory.
Et voilà! Line number of exactly where memory access was out of bounds. What else could we ask for? Of course, emacs.
You can call valgrind from emacs, inside an emacs shell buffer (M-x shell, then you are working in an usual shell), but you would like to visit the exact line in your code somewhat. Probably through either keyboard or mouse click. It turns out (I found it here while googling for a way to use valgrind via emacs) you can use compilation-minor-mode to do that... (M-x compilation-minor-mode), the problem then is that the return key gets mapped to compile-goto-error (i.e. you go to the line in the source with return), thus the terminal buffer no longer works as there is no way to send it commands. To solve this, I wrote this small piece of code and added to my .emacs:

(defun valgrind ()
(interactive)
(compilation-minor-mode)
(define-key compilation-minor-mode-map (kbd "")'comint-send-input)
(define-key compilation-minor-mode-map (kbd "S-")'compile-goto-error))

(add-hook 'shell-mode-hook 'valgrind)

Now when I start a shell window from within emacs, the function valgrind I defined is automatically loaded, starts compilation-minor-mode and redefines the return and shifted-return keys as I wanted. Now return works as usual in shell buffers, and shift-return visits error at point.I also made this function interactive (thus you can call it as M-x valgrind), in case I decide to remove the hook.
You may be also interested in:

8 Awesome Comments. Add Yours!:

mak163 said...

Thanks for the tip, I really like having this functionality. In compilation-minor-mode, my compiler runs when I type 'g', so I guess I will need to redefine that key as well?

RBerenguel said...

Indeed. If you have g in compilation minor mode bind you will have problems with interacting with your shell. Could you change it to M-g maybe (which is usually unbinded).

Tell me if you really find this trick useful!

mak163 said...

It appears that 'g' is not simply running the compile command. It is immediately opening a compilation buffer in a new window and running make -k. I am not sure how to rebind 'g' to nothing. Any ideas?

RBerenguel said...

D'oh. Probably you can do adding another custom command like I did for return:

(defun valgrind ()
(interactive)
(compilation-minor-mode)
....
(define-key compilation-minor-mode-map (kbd "")'self-insert-command))

(add-hook 'shell-mode-hook 'valgrind)

Adding this should change the mapping of G in compilation minor mode to just writing the letter g (which should be bound to self-insert-command). Here in my MacBook I don't have valgrind or these configuration options, if this does not work I'll check tomorrow in my netbook. I hope this does it!

mak163 said...

This took me a bit longer than it probably should have (I'm certainly no elisp programmer), but I was finally able to get this functionality working like I wanted. Essentially what the following elisp code does is create a function that will call valgrind with
"--leak-check=full" on a file that you specify in the mini-buffer. The output is displayed in a separate window in a new buffer call *Shell Command Output*. The active window is then set to that buffer and compilation-shell-minor-mode is activated. From there you can scroll to errors and jump to code.

It looks like by activating "compilation-shell-minor-mode" instead of "compilation-minor-mode", no keybindings from that compilation mode interfere with the shell input.

Thanks for posting about how you went about all this. It is has really been helpful in getting this working the way I wanted.

USAGE: M-x call-valgrind filename

ELISP:
; simple function for using valgrind in emacs
; to allow for jumping into code using valgrind output
(defun call-valgrind (file)
(interactive "fEnter file: ")
(shell-command (concat
"valgrind --leak-check=full " file))
(switch-to-buffer-other-window "*Shell Command Output*")
(compilation-shell-minor-mode t))

mak163 said...

Have you found a solution to the "jumping to code in other directories" problem? I have seen a patch for valgrind that makes it print out absolute paths, however, I would prefer not to have to patch valgrind every time a new version is released. I was hoping there might be an easy way to tell emacs to look in a few specified directories for the source files.

RBerenguel said...

Thanks for your tip and code! I'll have to try. I didn't found any solution because I debug small applications, with just a few files. So far, no problems moving through directories, but it is only one level up or down. When have you found this problem?

Michael said...

Any time that I am in a different directory than the source code that generates an error in valgrind, emacs asks me to browse to the directory that the file is located if I click on the offending file from within emacs.

This past weekend I posted a feature request with the valgrind community to have valgrind print out absolute path names so that clicking on a file in a different directory would cause emacs to jump to the source without prompting the user to enter the file path.

We'll see.