Link to main page and to computing


bad bug!

   Do you want to check for memory leaks with
   valgrind ?



What is Valgrind ?

Valgrind is an instrumentation framework for building dynamic analysis tools. There are Valgrind tools than automatically detect many memory management and threading bugs, and profile your programs in detail.


How may I run valgrind tools?

As a starting point, try running the memcheck tool. For a programme that is normally run with the following command line

./myexe his_arguments

you should simply do this:

valgrind ./myexe his_arguments

It is very usefull to add debug information to the executable at the compilation stage. Consider using -g in your g++ compilation command line. In order to put valgrind's large output into a log file, and to deepen its checks, try this:

valgrind --show-reachable=yes --leak-check=full --log-file-exactly=output.valgrind ./myexe his_arguments

First two options increase the size of the output. The third option redirects the output to the output.valgrind logfile.

At last, the most frequently used options can be saved into a rc file, either in the home directory ~/.valgrindrc or in the current directory ./.valgrindrc.

How to avoid printing some errors?

Many errors are due to third party softwares, that are used by your program. In particular, ROOT brings a lot of memory leaks and their subsequent errors in Valgrind's output. Even if it does not prevent these errors from happening in your software (i.e. your program will contain memory leaks thanks to ROOT), you can hide these errors in the report if you add the following option:

--suppressions=$ROOTSYS/etc/valgrind-root.supp

It could be needed to explicitely resolve the full path to this file. Change then $ROOTSYS accordingly (see the output of echo $ROOTSYS).

In case you write your own suppression rules, remember that if you use the "real" c++ class name (e.g. QListView::Show()), you should switch the demangle option to false:

--demangle=no

. The easiest way to generate a suppression rule file is to fast valgrind to generate it itself, using the --gen-suppressions=all option in the command line. After each error, in valgrind output, the corresponding suppression rule is written. Just copy-and-paste it into your suppression file. To be more generic, wildcard characters * can be used. As an example, here is a list of suppression rules that prevents valgrind from outputing errors related to the ROOT framework, for a specific program (called Delphes).


How to understand the output

The errors output by valgrind could be cryptic. Here are some indications to read the output file

Invalid read of size ...

You are trying to read some data which has been deleted [ref].

Conditional jump or move depends on uninitialised value(s)

You are using unitialised variable [ref].

Invalid free()

Mismatched free() / delete / delete []

You are trying for instance to use delete on a pointer that was not initialised with a new. When a memory is allocated with new, it should be deallocated with delete. Same for new [] and delete []. One should not mix these [ref].

Common errors with pointers

Pointer data member

When one of the data member of a class is a pointer, it is required to have (1) a good copy-constructor, (2) a good operator= and (3) a good destructor to handle it properly.
	   class MyClass { 
	     private: 
		unsigned int N;
		float * data;
		// ...
             public:
		MyClass();
		MyClass(const MyClass & mine);
		MyClass & operator=(const MyClass & mine);
		// ...
	   }

	   MyClass::MyClass() {
		N = 42; 
		data = new float[N]; 
		//...
           }

	   MyClass::MyClass(const MyClass & mine) {
		N = mine.N;
		data = new float[N];
		for (unsigned int i=0; i<N; i++) data[i] = mine.data[i];
	   }

	   MyClass& operator=(const MyClass & mine) {
		if(this==&ET) return *this;
		N = mine.N;
		data = new float[N];
		for (unsigned int i=0; i<N; i++) data[i] = mine.data[i];
		return *this;
	   }

	   MyClass::~MyClass() { delete [] data; }
        

argv/argc for TApplication

Using ROOT TApplication may require to transfer to the application the arguments of your command line, i.e. the contents of *argv[]. You must be cautious to handle properly the char ** relic coming from C. Here is one solution to avoid possibly related memory leak.
	int main(int argc, char *argv[]) {

	  int appargc = 2;
	  char *appName= new char[20];	  sprintf(appName,"Delphes");
	  char *appOpt= new char[20];	  sprintf(appOpt,"-b");

	  char *appargv[] = {appName,appOpt};
	  TApplication app(appName, &appargc, appargv);

	  delete [] appName;
	  delete [] appOpt;
	  //...
	}
	
It should be noted that the appargv variable should not be deleted, as it has not been created with a new. In general, when possible it is far more efficient to use C++ string (remember the c_str() member function that returns a char*).

Dernière mise-à-jour: 21/03/2009