Entry tags:
booyeah, I'm good!
So some months ago I worked on an AVL tree in pure C. My main goal was to get self-balancing happening at all, to demystify that process, and I did that; getting the code to be robust or even asymptotically appropriate (I'm still calculating heights every time I need to, not caching and updating them) was far down the priority list. So, while I tried to be correct in handling memory, it would not have surprised me if subtle bugs still existed.
My past work experience didn't emphasize use of static analysis tools. I think I played with lint a bit on my own, but relying on it or valgrind wasn't a thing. I finally investigated them today, ending up with cppcheck for source code check, and valgrind for what it does. And ran them on my directory of C/C++ exericses, which as small exercises, could easily have had lots of problems.
...not so much! cppcheck found a few problems, most notably a missing return value I wasn't testing properly in linked list, and a realloc bug[1] in my memoized Fibonacci table, and an unset ID variable in a threading program, but nothing else, including in the AVL tree or the new C++ hash table.
valgrind found some memory leaks in linked list and AVL tree... only because the testing main() for each was creating structures and then not freeing them before exit, because who cares at that point? With a manual destroy added, both check out clean. Which the list really should, it's pretty simple, but I'm stoked about the AVL tree doing so, since it's complex and memory correctness wasn't a top priority. Seems like I do have good habits.
There's also clang's static analyzer, supposedly deeper than cppcheck, though much slower to use. It's happy with my codes too.
Of course, valgrind can only test what's executed, so more use might uncover more bugs, but still, I feel good.
[1] ptr = realloc (ptr, ...) sets ptr to NULL if the realloc fails, which means a memory leak if nothing else is pointing to what ptr had been pointing to. Not having used realloc much, plus also not worrying about errors in a tiny program, this didn't stand out to me.
My past work experience didn't emphasize use of static analysis tools. I think I played with lint a bit on my own, but relying on it or valgrind wasn't a thing. I finally investigated them today, ending up with cppcheck for source code check, and valgrind for what it does. And ran them on my directory of C/C++ exericses, which as small exercises, could easily have had lots of problems.
...not so much! cppcheck found a few problems, most notably a missing return value I wasn't testing properly in linked list, and a realloc bug[1] in my memoized Fibonacci table, and an unset ID variable in a threading program, but nothing else, including in the AVL tree or the new C++ hash table.
valgrind found some memory leaks in linked list and AVL tree... only because the testing main() for each was creating structures and then not freeing them before exit, because who cares at that point? With a manual destroy added, both check out clean. Which the list really should, it's pretty simple, but I'm stoked about the AVL tree doing so, since it's complex and memory correctness wasn't a top priority. Seems like I do have good habits.
There's also clang's static analyzer, supposedly deeper than cppcheck, though much slower to use. It's happy with my codes too.
Of course, valgrind can only test what's executed, so more use might uncover more bugs, but still, I feel good.
[1] ptr = realloc (ptr, ...) sets ptr to NULL if the realloc fails, which means a memory leak if nothing else is pointing to what ptr had been pointing to. Not having used realloc much, plus also not worrying about errors in a tiny program, this didn't stand out to me.