Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Program terminates early with valgrind memcheck

Tags:

c

gcc

gdb

valgrind

I have a C-programm (a lot of numerics and too long to post) which I compile with

gcc -g -O0 program.c -o program

I am trying to debug it using gdb and valgrind memcheck. After some changes on the code I found that

valgrind --tool=memcheck --log-file=output.log ./program

gives

==15866== Memcheck, a memory error detector
==15866== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==15866== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==15866== Command: ./program
==15866== Parent PID: 3362
==15866== 
==15866== Warning: client switching stacks?  SP change: 0xbe88bcd8 --> 0xbe4e1f70
==15866==          to suppress, use: --max-stackframe=3841384 or greater
==15866== Invalid write of size 4
==15866==    at 0x804B7BE: main (program.c:1396)
==15866==  Address 0xbe4e1f74 is on thread 1's stack
==15866== 
==15866== Invalid write of size 4
==15866==    at 0x804B7C2: main (program.c:1396)
==15866==  Address 0xbe4e1f70 is on thread 1's stack
==15866== 
==15866== Invalid read of size 4
==15866==    at 0x4320011: on_exit (on_exit.c:34)
==15866==    by 0x43064D2: (below main) (libc-start.c:226)
==15866==  Address 0xbe4e1f70 is on thread 1's stack
==15866== 
==15866== Invalid read of size 4
==15866==    at 0x4320022: on_exit (on_exit.c:37)
==15866==    by 0x43064D2: (below main) (libc-start.c:226)
==15866==  Address 0xbe4e1f74 is on thread 1's stack

and many more of this kind.

valgrind --tool=memcheck --max-stackframe=3841384 --log-file=output.log ./program

does not print any errors. But what puzzles me is that with both valgrind calls the program exits early (without error messages) and does not do the computation it is supposed to do. The behaviour with same compiler options but run without valgrind is entirely different and looks pretty normal. I suspect a memory error however and want to use valgrind to find it. My question therefore: What kind of error can make a program bahave so differently when executed with valgrind? And if these are memory related errors how can I identify it? Note that it is clear to me that I can "debug by hand" to locate it. But can I maybe run gdb with valgrind to see where it exits.

like image 701
highsciguy Avatar asked Sep 27 '12 15:09

highsciguy


People also ask

Can valgrind be wrong?

Yes, there are false positives with Valgrind, that's why it has suppression files for particular glibc and gcc versions, for example. The false positives may arise if you are using older valgrind with newer gcc and glibc, i.e., valgrind 3.3 with glibc 2.9.

What is Memcheck valgrind?

Valgrind Memcheck is a tool that detects memory leaks and memory errors. Some of the most difficult C bugs come from mismanagement of memory: allocating the wrong size, using an uninitialized pointer, accessing memory after it was freed, overrunning a buffer, and so on.

How do you fix a valgrind memory leak?

This issue is located at line 37 of "valgrind-tests.cc" in this example. The main problem of valgrind is that, as I said earlier, it displays memory leaks or memory warnings (like forgotten pointers) from libraries you use. To clean your logs, you can write valgrind rule files called "suppression files".

How can I see valgrind errors?

Look for function names and line numbers If you compile your program with the -g flag, Valgrind will show you the function names and line numbers where errors occur.


1 Answers

I originally answered in the comments:

You're probably causing a stack overflow. Are you allocating "large" arrays on the stack? E.g. double myArray[10000000]; If so then you should replace such allocations with heap memory using malloc and free.

I wrote a short c-program to intentionally cause a stack overflow like this and check what valgrind reports:

#include <stdio.h>

int main(){

  // imax*sizeof(double) is too big for the stack.
  int imax = 10000000;
  double test[imax];

  // I do a little math to prevent the stack overflow from being optimized away if -O3 is used.
  test[0]=0;
  test[1]=1;
  for(int i=2; i<imax; i++)
    test[i]=0.5*(test[i-1]+test[i-2]);
  printf("%e\n", test[imax-1]);

}

Sure enough, valgrind comes up with:

==83869== Warning: client switching stacks?  SP change: 0x104802930 --> 0xffbb7520
==83869==          to suppress, use: --max-stackframe=80000016 or greater
==83869== Invalid write of size 8
==83869==    at 0x100000ED0: main (in ./a.out)
==83869==  Address 0xffbb7520 is on thread 1's stack

along with tons of other error messages, and eventually quits with a Segmentation fault: 11

like image 140
Douglas B. Staple Avatar answered Sep 27 '22 16:09

Douglas B. Staple