Your JoeDog loves C but he hates memory management. That’s why he writes objects in C. They make managing memory easier. Still, he’s been know to cause a memory leak or two … okay, maybe a few more than that.
Valgrind is supposed to help identify those fsckers. You run a program inside valgrind and it checks your memory utilization. Awesome! Except when it’s not.
Your JoeDog has had zero point zero luck with valgrind. He’s been working on a snippet that will be incorporated into Your Fido. Your JoeDog loves snippets. By reducing complexity they allow him to focus on the integrity of the new code. In this particular snippet, he placed the new functionality inside a loop to check its long-running performance. The damn thing leaked!
“How did you know it was leaking?”
“I watched its memory usage in top and it continued to expand.”
“Well that sucks.”
“Indeed.”
So Your JoeDog ran the program in valgrind like this:
valgrind -v --leak-check=full --tool=memcheck ./haha
After it completed its iterations, valgrind had this to say:
==21112== HEAP SUMMARY: ==21112== in use at exit: 0 bytes in 0 blocks ==21112== total heap usage: 0 allocs, 0 frees, 0 bytes allocated ==21112== ==21112== All heap blocks were freed -- no leaks are possible
What the hell? This thing was leaking all over the place. Now Your JoeDog may have done something stupid. Instead of memory leaks, he might have created memory hogs. “What are memory hogs?” They are allocated resources that are no longer used but with references that are still maintained. Valgrind won’t identify a memory hog as a memory leak. But this was a snippet and an audit was easy. There were no hogs; something was leaking.
After an extensive audit, Your JoeDog identified the leak. It wasn’t in the snippet. He was using a dynamic array from array.c Here’s the offending code:
ARRAY array_destroy(ARRAY this) { int i; for (i = 0; i < this->length; i++) { xfree(this->data[i]); } xfree(this->data); this = NULL; return this; }
Your JoeDog freed everything but the array object itself. Here’s the fix:
ARRAY
array_destroy(ARRAY this)
{
int i;
for (i = 0; i < this->length; i++) {
xfree(this->data[i]);
}
xfree(this->data);
xfree(this);
this = NULL;
return this;
}
It’s not clear why valgrind didn’t identify that. Any thoughts?