Valgrind

  1. Valgrind Memcheck
  2. Valgrind Tutorial
  3. Valgrind Memcheck

Written by Nate Hardison, Julie Zelenski and Chris Gregg, with modifications by Nick Troccoli

Click here for a walkthrough video.

Valgrind command

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. These types of errors are tricky, as they can provide little debugging information, and tracing the observed problem back to underlying root cause can be challenging. Valgrind is here to help!

Valgrind

Valgrind reports two types of issues: memory errors and memory leaks. When a program dynamically allocates memory and forgets to later free it, it creates a leak. A memory leak generally won't cause a program to misbehave, crash, or give wrong answers, and is not an urgent situation. A memory error, on the other hand, is a red alert. Reading uninitialized memory, writing past the end of a piece of memory, accessing freed memory, and other memory errors can have significant consequences. Memory errors should never be treated casually or ignored. Although this guide describes about how to use Valgrind to find both, keep in mind that errors are by far the primary concern, and memory leaks can generally be resolved later.

Valgrind is a system for debugging and profiling Linux programs. With its tool suite you can automatically detect many memory management and threading bugs, avoiding hours of frustrating bug-hunting and making your programs more stable. You can also perform detailed profiling to help speed up your programs and use Valgrind to build new tools. Valgrind is an instrumentation framework for building dynamic analysis tools. There are Valgrind tools that can automatically detect many memory management and threading bugs, and profile your programs in detail. You can also use Valgrind to build new tools.

Like the debugger, Valgrind runs on your executable, so be sure you have compiled an up-to-date copy of your program. Run it like this, for example, if your program is named memoryLeak:

Valgrind

Valgrind will then start up and run the specified program inside of it to examine it. If you need to pass command-line arguments, you can do that as well:

When it finishes, Valgrind will print a summary of its memory usage. If all goes well, it'll look something like this:

This is what you're shooting for: no errors and no leaks. Another useful metric is the number of allocations and total bytes allocated. If these numbers are the same ballpark as our sample (you can run solution under valgrind to get a baseline), you'll know that your memory efficiency is right on target.

Memory errors can be truly evil. The more overt ones cause spectacular crashes, but even then it can be hard to pinpoint how and why the crash came about. More insidiously, a program with a memory error can still seem to work correctly because you manage to get 'lucky' much of the time. After several 'successful' outcomes, you might wishfully write off what appears to be a spurious catastrophic outcome as a figment of your imagination, but depending on luck to get the right answer is not a good strategy. Running under valgrind can help you track down the cause of visible memory errors as well as find lurking errors you don't even yet know about.

Each time valgrind detects an error, it prints information about what it observed. Tt esports black gaming mouse v2 dpi. Each item is fairly terse-- the kind of error, the source line of the offending instruction, and a little info about the memory involved, but often it is enough information to direct your attention to the right place. Here is an example of valgrind running on a buggy program:

The ERROR SUMMARY says there is one error, an invalid write of size 1 (byte, that is). The bad write operation was observed at line 58 in myprogram.c. Let's look at the code:

Looks like an instance of the classic strlen + 1 bug. The code doesn't allocate enough space for the '0' character, so when strcpy went to write it at frag[strlen(buffer)], it accessed memory beyond the end of the malloc'ed piece. Despite the code being clearly wrong, it often may appear to 'work' because malloc commonly rounds up the requested size to the nearest multiple of 4 or 8 and that extra space may cover the shortfall. 'Getting away with it' can lead you to a false sense of security about the code being correct. The next run might get a strange crash that you might write off as a fluke. But vigilantly using valgrind can inform you of the error so you can find and fix it, rather than wait for an observed symptom that may be hard to reproduce.

There are different kinds of memory errors that you may see in the valgrind reports. The most common are:

  • Invalid read/write of size X The program was observed to read/write X bytes of memory that was invalid. Common causes include accessing beyond the end of a heap block, accessing memory that has been freed, or accessing into an unallocated region such as from use of a uninitialized pointer.
  • Use of uninitialised value or Conditional jump or move depends on uninitialised value(s) The program read the value of a memory location that was not previously written to, i.e. uses random junk. The second more specifically indicates the read occurred in the test expression in an if/for/while. Make sure to initialize all of your variables! Remember that just declaring a variable doesn't put anything in its contents--if you want an int to be 0 or a pointer to be NULL, you must explicitly state so. Note that Valgrind will silently allow a program to propagate an uninitialized value along from variable to variable; the complaint will only come when(if) it eventually uses the value which may be far removed from the root of the error. When tracking down an uninitialized value, run Valgrind with the additional flag --track-origins=yes and it will report the entire history of the value back to the origin which can be very helpful.
  • Source and destination overlap in memcpy() The program attempted to copy data from one location to another and the range to be read intersects with the range to be written. Transferring data between overlapping regions using memcpy can garble the result; memmove is the correct function to use in such a situation.
  • Invalid free() The program attempted to free a non-heap address or free the same block more than once.

Memory errors in your submission can cause all sorts of varied problems (wrong output, crashes, hangs) and will be subject to significant grading deductions. Be sure to swiftly resolve any memory errors by running Valgrind early and often!

Bluestacks 1 uptodown. You can ask Valgrind to report on memory leaks in addition to errors. When you allocate heap memory, but don't free it, that is called a leak. For a small, short-lived program that runs and immediately exits, leaks are quite harmless, but for a project of larger size and/or longevity, a repeated small leak can eventually add up. For CS107, we will expect you to deallocate all memory at the end of program execution.

For an example, let's take this memoryLeak.c program:

If we compile and run this, here is the output we get:

This seems to be ok, but let's run it under Valgrind, just to be sure:

It's pretty easy to tell when there's a leak: the alloc/free counts don't match up and you get a LEAK SUMMARY section at the end. (note that it says 2 allocs even though we only call malloc once. Why? Because srand/time allocate memory in their implementations, but they free it as well!). Valgrind also gives a little data about each leak -- how many bytes, how many times it happened, and where in the code the original allocation was made. Multiple leaks attributed to the same cause are coalesced into one entry that summarize the total number of bytes across multiple blocks. Here, the program memoryLeak.c requests memory from the heap and then ends without freeing the memory. This is a memory leak, and valgrind correctly finds the leak: 'definitely lost: 4,000 bytes in 1 blocks'

Valgrind categorizes leaks using these terms: Adobe flash player 10 2 free download for mac.

  • definitely lost: heap-allocated memory that was never freed to which the program no longer has a pointer. Valgrind knows that you once had the pointer, but have since lost track of it. This memory is definitely orphaned.
  • indirectly lost: heap-allocated memory that was never freed to which the only pointers to it also are lost. For example, if you orphan a linked list, the first node would be definitely lost, the subsequent nodes would be indirectly lost.
  • possibly lost: heap-allocated memory that was never freed to which valgrind cannot be sure whether there is a pointer or not.
  • still reachable: heap-allocated memory that was never freed to which the program still has a pointer at exit.
Valgrind

These categorizations indicate whether the program has retained a pointer to the memory at exit. If the pointer is available, it will be somewhat easier to add the necessary free call, but it doesn't change that the fact that all are leaks-- that is, memory that was heap-allocated and never freed.

Given that leaks generally do not cause bugs, and incorrect deallocation can, we recommend that you do not worry about freeing memory until your program is finished. Then, you can go back and deallocate your memory as appropriate, ensuring correctness at each step.

If you want more information, you need to include the options --leak-check=full and --show-leak-kinds=all

Because we compiled with the -g flag, valgrind is able to tell us exactly where in our program the leak was created:

In other words, on line 9 in memoryLeak.c, we allocated the memory and it was never freed. This can be super-helpful when debugging your programs!

For more information about Valgrind, also check out the full valgrind manual.

My program runs very slowly under Valgrind. Should I be concerned?

No. Valgrind is running your program in a simulated context and monitoring the runtime activity. Depending on how memory-intensive the program is, this extra checking can slow down a program by 2-5x. This is completely expected.

Valgrind says I leaked memory because of a call to malloc() in main(), but I don't call malloc() in main()! What's going on?

This report can also be a result of calling a library function in main() that itself calls malloc() internally. Common examples include fopen() and strdup(). Make sure to fclose any fopened FILE*s, and free any strduped char*s.

My program runs fine and produces correct output but the Valgrind report shows memory errors. Can I ignore these?

No. An error may not have an observable runtime consequence in some situations but that doesn't mean it doesn't exist. The error is a ticking time bomb that can go off at anytime. Ignoring it and counting on your code continuing to 'get lucky' is a risky practice. Make sure your code always runs Valgrind-clean!

My valgrind report includes an ominous-looking entry something like this: 'Warning: set address range perms: large range'. What is this and do I need to worry about it?

Valgrind prints this warning when an unusually large memory region is allocated, on suspicion that the size may be so large due to an error. If the intention of your code was to allocate a large block, then all is well.

My valgrind report suggests to rerun with -v for 'counts of suppressed errors'. What are these? Should I worry about them?

Pay no attention. Some library code does unusual things which can trigger reports from Valgrind even when operating correctly. Those errors/leaks are suppressed as they are known to be spurious. The -v flag causes valgrind to provide verbose commentary about its internal handling of these events. You can safely ignore all suppressed events; no need for you to wade through the verbose chatter.

When I run valgrind with no extra arguments, the ERROR SUMMARY says 0 errors, but the exact same run adding the --leak-check option then reports N errors from N contexts. Do I have errors or don't I?

With leak-check enabled, each distinct leak found by valgrind is included in the count of errors. Without leak-check enabled (the default), it doesn't enumerate/count leaks, so only actual memory errors are reported in the summary count.

I get a 'Permission denied' message when I attempt to run a particular executable under valgrind even though I can run the program normally. How do I fix?

Valgrind refuses if you don't have execute permission according to the file mode of the executable. The file mode is mostly irrelevant on our myth systems (the directory-based AFS permissions take precedence), but Valgrind is paying attention anyway. The command ls -l executable_file shows the file mode bits, the x's indicate execute permission for owner/group/other. Use the command chmod a+x executable_file to enable execute permission for all users.

Valgrind is a program that checks for both memory leaks and runtime errors. A memory leak occurs whenever you allocate memory using keywords like new or malloc, without subsequently deleting or freeing that memory before the program exits. Runtime errors, as their name implies, are errors that occur while your program is running. These errors may not cause your code to crash, but they can cause unpredictable results and should be resolved.

Memory Leaks

If your program has memory leaks, they will appear at the bottom of the Valgrind output, as follows:

Ultimately, your goal is to get each of these categories down to 0 bytes in 0 blocks. When this happens, the Leak Summary output will change to look as follows:

Runtime Errors

Valgrind outputs runtime errors together with your program's output. For example, consider the following Valgrind segment:

In the middle of running my code, Valgrind discovered a runtime error, in this case, Invalid write of size 4. Notice that it gives us a 'stack trace', in other words, a list of which functions were called to get to the point where this error occurred. In this case, main() called function1(), which called function2(), which called function3(), which called function4(). function4() is where the error occurred. Notice that Valgrind even gives a line number: our error occurred in the file valgrind.cpp on line 4.

Valgrind Memcheck

Sometimes, Valgrind will report that an error occurred in a function that you didn't even write. For example:

As you can see in the stack trace, an error occurred in the file write.c on line 27. But you didn't even write that! When this happens, the best thing to do is to follow the stack trace backwards until you find a function that you did write. In this example, we would follow the stack trace back until we found the main() function, specifically line 180 in valgrind.cpp.

Let's now consider the most frequent Valgrind errors that you might face in this class:

Conditional jump or move depends on uninitialized value(s)

Valgrind

Valgrind Tutorial

This error message means that you have a loop or if statement that is dependent on an uninitialized variable (a variable whose value you haven't set). In the example below, notice that the integer x is only set if userInput is equal to true. But then, no matter what, we use x in the for-loop condition, even though it might not be set. This creates problems, because if you don't set the value of the variable, it will be set to some unknown value.

Invalid write of size n

This error message most often occurs if you have written outside the bounds of memory you have allocated. For example, suppose you allocate an array of integers with 5 items, but then try to access the 8th element:

Mismatched (or Invalid) free() / delete / delete[] / realloc()

This error message can have several causes. The most common reason is forgetting to use delete[] with dynamically allocated arrays. In this example, the valgrind error could be corrected by simply adding the square brackets after delete.

This can also occur if you don't correctly delete the memory you've allocated. Anytime you use new, you must delete with delete. Anytime you use malloc, you must delete using free. Attempting to mix and match, as seen below, will cause a Valgrind error:

One other thing that can cause this problem is deleting the same thing twice:

Stack overflow in thread

In labs that use recursion, such as BST, you may run into this error. Most frequently this occurs when you don't have exhaustive base cases for a recursive function. Without all the necessary base cases, your recursive function will continually call itself until there is no more memory on the stack to call it.

Process terminating with default action of signal 11 (SIGSEGV)

This means that your program crashed with a Segmentation Fault. A segmentation fault generally occurs if you try to access memory that is already reserved by the system. In this class, this most commonly occurs if you try to access a data member of a NULL pointer, like this:

Process terminating with default action of signal 15 (SIGTERM)

Valgrind Memcheck

In the autograder output, you will almost always see this error when your program's execution timed out (in this class, the time limit is 5 seconds). Like the stack overflow issue, this can happen with recursive functions that are missing necessary base cases. If this is the case, your Valgrind output will look something like this:

Notice that function1() continually called itself over and over until we ran out of time.