Tools For Understanding Code? 383
ewhac writes "Having just recently taken a new job, I find myself confronted with an enormous pile of existing, unfamiliar code written for a (somewhat) unfamiliar platform — and an implicit expectation that I'll grok it all Real Soon Now. Simply firing up an editor and reading through it has proven unequal to the task. I'm familiar with cscope, but it doesn't really seem to analyze program structure; it's just a very fancy 'grep' package with a rudimentary understanding of C syntax. A new-ish tool called ncc looks promising, as it appears to be based on an actual C/C++ parser, but the UI is clunky, and there doesn't appear to be any facility for integrating/communicating with an editor. What sorts of tools do you use for effectively analyzing and understanding a large code base?"
Wait for cenqua's solution (Score:5, Funny)
Been there... (Score:5, Insightful)
There are some horrible programmers out there and I have on many occasions been tasked with cleaning up their messes. In your situation I would suggest either a) try to figure out if it would take less time for you to implement it in a clean and maintainable way or b) find someone else you can hire who knows the code base or at least is more familiar with the specific problem.
If you can't do a or b then you're screwed. In that situation, personally, I would either quit, ask for a different project, or print out the whole source code and sit back with a pen and start studying and commenting - one of the few tasks for which I still prefer dead trees.
Re:Been there... (Score:5, Insightful)
Been there, will never return (Score:3, Interesting)
I had a very wise undergrad EE prof who said on the first day of design class that we needn't worry about the many "complicated" things that we would have to design during the course because we had already completed all of our circuit analysis courses. He said it's much harder to figure out the details of someone's design than to design it yourself. Same applies here in software. I've been there working with other's undocumented code and quite frankly it was infrequently that I left the project with more re
Re: (Score:3, Funny)
Ah, so really there are two kinds of things: those which are dualities and those which are not?
Re: (Score:3)
Stepping Through (Score:5, Insightful)
If there's no one at your company that can help answer your questions and bring you up to speed, I feel for you - your employers ought to know enough to give you some extra margin. It can be very hard to take over a large code base without some human-to-human handover time.
Also, is it an object-oriented system? I assume that it's not, based on your post, but you don't say either way. If it is, the important aspects of program flow often live in the interactions between classes and objects and the business logic is decentralized. OO is great, but it can be harder to reverse-engineer business logic because it's distributed among various classes. A debugger that lets you step through running code is almost essential in this case.
Re:Stepping Through (Score:5, Insightful)
Place a breakpoint somewhere you think will get hit (e.g. main), and then start stepping over and into functions. I usually attack this problem as follows:
Place breakpoint. Use step-in functionality to drop down a ways into the program, looking at things as I go. What are they doing, how do they work, etc.
Once I feel like I understand how a section of code works, I step over that code on subsequent visits. If I feel like this isn't taking me fast enough, I let the program run for a bit, then randomly break the program and see where I am.
Lather, rinse, repeat.
Also, this should go without saying, but you should ask someone who works with you for a high-level overview of what the code is doing. The two of these combined should get you up to speed as quickly as possible.
Re: (Score:3, Informative)
Clearly you don't write (or at least read source for) applications of any substance as that would be mildly described as tedious if not impossible.
One of the best ways to understand code is to do so visually with the software equivalent of blueprints. UML is generally considered a very capable way of modeling/communicating both static structures and dynamic behavior of software. There exist any number of tools that are capable of reverse-engineering existing source into UML. Two tools that I consider t
Re: (Score:3, Insightful)
Clearly you don't write (or at least read source for) applications of any substance as that would be mildly described as tedious if not impossible.
I have no idea how you formulated this from parent based from 2 or 3 sentences.
One of the best ways to understand code is to do so visually with the software equivalent of blueprints. UML is generally considered a very capable way of modeling/communicating both static structures and dynamic behavior of software.
A lot of times a programmer is stuck without those t
Re: (Score:3, Informative)
Re:Stepping Through (Score:5, Informative)
Well, the learning curve is certainly important in the real world, although I expect a professional to know his or her tools before they arrive on the job. But there are a metric crapload of things I like better about Visual Studio that make it a much more effective debugger than gdb, in my opinion. (Note that I am not a big gdb user, so I may be cutting it a bit short in the feature set here. My apologies in advance if I do so.)
Things I've found I prefer include many tool windows simultaneously showing the states of registers, memory, the call stack, an object or seven (expanded to show a few properties), and automatic resolution of virtually every symbol and name, including the operating system (although you have to download the symbol files for your OS version from Microsoft.) And you still have full navigation through the source.
Simply hovering the mouse over a symbol will bring up a tool-tip to display the contents. If you highlight an entire expression such as pFoo->pBar->Blah.count+7 and hover, the tooltip will display the calculated result.
You can set a temporary breakpoint by setting the cursor on a line of code and clicking "run to cursor." You can run, single step, run to the current cursor, or run till function return. That last one is great for re-entering a function multiple times to test different conditions.
The variables window contains the current call stack as a dropdown list -- changing the stack lets you see the newly-local variables. Watch windows can display data as hex or decimal, just right click and select. Watch entries can even be used as calculators (enter a literal value, such as 0xf0 + 12, and it will display the results.)
In the watch windows, you can also call arbitrary functions (good for testing without driving your code to that point) or other functions in your memory space, such as the C runtime memory checkers. If you're trying to track an errant pointer, create a debug build, start running and break, type _CrtCheckMemory() into a watch window, and every time the watch window is refreshed, it will check all your fenceposts. You might get lucky and spot your corruption as it happens. The /GZ compiler option will perform a similar task at the function level, but this would let you do it at a line level.
There are also dozens of possible formats it can display your watch variables in -- suffix a pointer with ,s and it'll display the contents as an ASCII string. Only see one byte because of Unicode? Suffix the pointer with ,su and you'll see the unicode string. A ,wm suffix displays window messages by name. ,hr suffix displays HRESULTs by name.
The memory windows will highlight in another color any data that's changed since the last time it was refreshed, whether it be a single step or a previous breakpoint. You can have memory displayed as bytes, shorts, or longs. And with the newer visual studios, you can have multiple memory windows, so you can keep track of two, three or four arrays simultaneously. You simply drag and drop them wherever they're convenient, then step through the code and watch for colored variables indicating change.
Again, all these windows are automatically updated every time the debugger drops from the program to your control. I've got two 17" monitors, and I can fill them both. The problem with debugging is that sometimes you are really starting blind, and the faster you can get more information, the less time you waste debugging.
There's a cute "magic trick" I like to show people with the memory window and the disassembly window. Let's say you've had a crash, and attached the debugger to the running program. You're looking at a corrupt stack in the call stack window -- just one line of garbage data. What to do? Where did it break? Enter @ESP in the memory window. Change the view to 'long' and it displays the memory as 8-digit numbers. If y
Re: (Score:3, Informative)
I used to teach a course in debugging with Visual Studio, and I basically trawled through my syllabus looking for the cool tricks. Using the stack-crash demo to drop into the source code of the crashing module is a real attention-grabber.
I found debugging in gdb to be a lot like debugging in WinDBG. You have to learn a lot of esoteric commands that you don't use very often, so it takes a lot of practice to learn them. And if you aren't constantly searching for the side effec
Mod parent up (Score:5, Insightful)
I would suggest a slight variation on the theme. Fire up the application, start it on one of its typical tasks, and then interrupt it in the debugger to catch it. While the process is stopped mid-flight, take note of the call stack to see which classes and methods are being used. Maybe step through a few calls, then let the program run some more.
By doing this repeatedly, you will quickly get a sense for which parts of the code see the most action, and would provide the most obvious places to start studying the code base, and provide the best bang-for-buck return on your time.
Re:Mod parent up (Score:5, Informative)
Good advice -- breaking randomly. However, it works best in CPU-intensive applications. If the app is mostly idle and event-driven, you're best off searching the code and looking for a place to set breakpoints.
Also, when I use the debugger to help understand some new code, often I'll open a text file and build a "trace" as I go. As I explore things in the debugger and find new call stacks, I add more detail to the trace, in a hierarchical (indented) style. Then I save the traces in case I forget something later.
As for the original question, I would recommend staying focused. Don't go all over the program trying to understand every system at once. Pick a specific part you really need to understand (say, based on a task you have to do) and focus on understanding that.
Unfortunately, the best tool for understanding code is experience. Not theory and not some fancy visualization program. Once you've seen a lot of different code, you come to recognize what each person was thinking when they wrote it. Once that kind of thing comes easily, you no longer find it necessary to bitch about each different programmer's coding style (as some do). So in a way, the guy who posts this question is lucky to have such a big pile of code in front of him.
Re:Mod parent up (Score:4, Insightful)
Most of my productive code learning was in the first three months of bug-fixing. I think that's why most newhires end up on bug fixing as a rule - it's the fast-path to comprehension.
Re:Mod parent up (Score:4, Insightful)
If only there were some way to automatically generate this information, this "profile" of the running code, if you will.
Not for a "large" codebase... (Score:4, Insightful)
It seems like in those cases I end up working from effects... I note some program behavior and then try to find exactly what causes that behavior, which can be surprisingly difficult if you are dealing with the "right" kind of code. After a while, though, the patterns begin to emerge in the system as a whole.
Re:Not for a "large" codebase... (Score:5, Insightful)
You are correct. All these people talking about using a debugger and so on... That does NOT work on larger projects any on fairly simple ones. "Large" projects might have 250 source code files and thousands of functions or classes and likely a dozen or so interacting executable programs. I've seen print outs of source code that fill five bookcase shelves. No one could ever read that.
I've had to come up to speed on million+ lines of code projects many times. The tool i use is pencil and paper
The first step is to become an expert user of the software. Just run the thing, a lot and learn what it does. Looking at code is pointless untill yu know it well as a user.
Re: (Score:3, Insightful)
if... there is such an animal around still for the environment in question.
Re:Stepping Through (Score:4, Insightful)
Re: (Score:3, Insightful)
Pick a tool to wrap something, start writing little bits to excercise the code.
You can comment and version unit tests, giving a sense of history.
Debuggers, on the other hand, mostly exist in the present tense.
Sure, you learn something now, but how about some breadcrumbs for later?
Tests (Score:4, Interesting)
Another great tool is valgrind+KCachegrind - it gives you really nice call trees. Vtune can do something similar as well, but IMHO the output is not as good as in KCachegrind. The only problem, of course, is that valgrind makes your program very slow and, it is, AFAIK, not available on MS Windows.Vtune, OTOH, runs the program at normal speed, but it's calltree output is ugly, at least on Linux.
If these two options are not for you than you might add a trace output to each function. IMO this is better than using a debugger - especially in C++ with BOOST and STL, where a lot of stepping goes through inline functions.With proper logging levels you can get a very useful output to see what's going on. It helps to understand the code, and it also helps, if you hit a bug.
Re: (Score:3, Insightful)
Re:Stepping Through (Score:4, Insightful)
Re:Stepping Through (Score:5, Insightful)
Doxygen (Score:5, Informative)
For C++ code, Doxygen [stack.nl] can be useful, as it shows the class inheritance. As requested, it uses a (rudimentary) parser. It works with several other languages too, although I can't vouch for its utility for them.
Re: (Score:2)
I would google for that, but I'm under deadline myself... (but yet still reading
Re: (Score:3, Informative)
Re:Doxygen (Score:5, Informative)
Doxygen is more than a javadoc replacement.
I like Doxygen + Graphviz. Just set Doxygen to document all (instead of just the code with tags) and set it to generate class diagrams, call trees, and dependency graphs and allow it to generate a cross reference document that you can read using your web browser. Set the html generator to frame based, and your browsing of code will be easier. I would also set Doxygen to inline the code within the documentation.
I've use Doxygen to reverse engineer very large programs and had good luck with it. I will say Doxygen is not going to do all your work for you, but it will make your job easier. Especially if you add comments to the code as you figure each section out.
Now if you like to see the logical flow of each method then try JGrasp (jgrasp.org). It has a neat feature called CSD that allow you to follow the logic of the code a little better. It's a java based IDE so that may be a turn off for you. I do whole heartedly recommend the Doxygen (w/ Graphviz).
Good luck.
Re:Doxygen, and Extracting Software Architectures (Score:5, Informative)
If the system you need to understand has a really big undocumented architecture, then this presentation [uwaterloo.ca] might be useful to you (there is a research paper, but it's not free yet). In it, the authors present a systematic method of extracting the underlying architecture of the Linux kernel.
Re:Doxygen (Score:4, Informative)
When I was your age... (Score:2, Interesting)
(and GET OFF MY LAWN).
Re: (Score:3, Funny)
When I was your age...I use the Mark I eyeball, grep, emacs, and of course, the little gray cells.
(and GET OFF MY LAWN).
They have lawns at the old folks' homes these days?
Paper (Score:2, Insightful)
Re: (Score:2)
Re: (Score:3, Interesting)
Re: (Score:3, Funny)
Obviously a program with labels such as "Frodo" Sam" "Gondor" must be doing something Lordly with rings
and if you have labels such as "string1" "string2", then the program must be solving some particle physics problem involving string theory.
Need I add :-) :-) :-) ?
Re: (Score:3, Insightful)
Absolute tosh ! (Score:5, Insightful)
In fact, it nicely highlights the difference between "software engineers" and "code monkeys". Code monkeys just dive in; they never pause to think. In fact ... they tend to avoid thinking. It's not their strong point. After all ... they're paid to code, right? Not to think. Software engineers on the other hand, look before they leap and spot the places where they need to pay attention first. And they're systematic about it.
In fact, a software engineer will happily spend a day or two putting the right tools in place, *including* a full backup and a proper version management system for when he's going to have to touch anything.
The first thing you want to know about a new code base (after you find out what it's supposed to be doing) is its structure. Tools like Doxygen (see previous posts) show you that structure *far* quicker and *far* more reliably than any amount of dumb code-browsing can. And besides ... once you do it, you've got that documentation stashed away securely instead of milling around incoherently in your head (you'll have completely forgotten most of what you read by next month) or on disorganised pieces of note paper.
The second thing is to figure out if it calls any "large" functionalities like subroutine libraries or even stand-alone programs like databases, let alone if it makes operating system calls. The call-tree will give you an excellent view, and the linker files can complete the picture. You wouldn't be the first maintenance programmer who found out after months that his application critically depends on some other application he wasn't told about.
The third thing is to see where your code does dirty things. Let the compiler help you. Just compile your application with warnings on and have a look at what the compiler comes up with. You might be surprised (and horrified). Then compile with the settings used by your predecessor and check that your executable is bit-for-bit identical to what's running (you wouldn't be the first sucker who's given a slightly-off code base).
If performance is at all important, then running the whole thing for a night on a standard case under a good profiler will also tells you lots of important things. Starting with where your code spends its time, where it allocated memory and how much, and where the heavily-used bits of code are. All neatly written down in the profiler logs.
Finally, run your application with a tool to detect memory management errors the first chance you get. Useful tools are Valgrind (in a Linux environment), Purify (expensive, but probably worth it) under Windows, and sundry proprietary utilities under Unix. Just about 90% of the errors made in C programs come from memory management problems, and half of them don't show up except through memory leakage and overwritten variables (or stacks .. or buffers .. or whatever). You'll need all the help you can get here, and as far as these errors are concerned, dumb code browsing is useless. Just keep your head when looking at reports from such tools ... they can throw up false positives. Ask around on a forum with specific questions if you're allowed, or ask your supervisor. After all ... you showed due dilligence.
When you know all that (if you have the tools in place, all of this can be done within 1 day + 1 overnight run + 1 hour reading the profiler output), go ahead and trace through the code in a debugger. You'll be in a *far* better position to judge what you should be reading.
Re: (Score:3, Informative)
The question he's trying to answer is what does the code "do"? why does it exist? what problem does it solve? When you inherit some homegrown E
About "new tools" (Score:3, Interesting)
Well ... some good points, and some I'd say are too detailed at this point.
I totally agree with point (1). I forgot to mention it since I assumed (always a bad thing) that the author actually could compile and run the thing. An important point to keep in mind. Thanks for bringing it up.
Points (2)-(5) however all come after you've understood the basic structure of your code base.
Next, I'd say that a fairly junior software engineer trying to tackle a large unknown code-base without proper too
doxygen (Score:3, Informative)
Ctags (Score:3, Insightful)
Old School (Score:5, Funny)
Understand C++ (Score:5, Informative)
Re:Understand C++ scitools.com (Score:2)
I highly recommend it. Well worth the $500 for it.
RR & EA (Score:3, Informative)
Re: (Score:2)
I've used Borland's Together in the past and found it really helpful for C++/Java code. It can be really helpful for coming up to speed a code base's class hierarchy. Unfortunately, when I tried it on a large C++ code base where I'm currently working, after loading the code base in it seemed to go into some sort of a analysis phase and then eventually crashed.
I'm not sure what the problem was. A sales droid called to check in on my download, passed the crash info on to a techie, and said I'd get a call ba
Reverse Engineer? (Score:2)
Re: (Score:2)
But yes, C is a few percent faster a
You must have inherited my old project (Score:5, Funny)
When I am particularly frustrated (Score:2)
What I do (Score:5, Informative)
ETrace : Run-time tracing http://freshmeat.net/projects/etrace/ [freshmeat.net]
This book is worth a read http://www.spinellis.gr/codereading/ [spinellis.gr]
Draw some static graphs of functions of interest using CodeViz http://freshmeat.net/projects/codeviz/ [freshmeat.net]
Write lots of notes, preferably on paper with a pen rather than electronically.
Non-sequitur time (Score:2)
Re: (Score:2)
I find the best thing is to do the drawing myself. It might take a couple of attempts, but in the process you have to dig into the details and discover the structure. The extra interaction with the code gives a more indepth understanding. If I can draw it, then I can create it, fix it, and explain it to someone else. If I can't draw a particular thing to a desired level of detail (whether it's a piece
Answer (Score:5, Funny)
Wait, were you talking about software?
Re: (Score:2)
Yes, but what happens when the tool asks Slashdot how to understand the code?
Re: (Score:2)
doxygen - with full source option (Score:3, Interesting)
Creating small demo apps that use the code can also help.
mhack
GNU Global (Score:4, Informative)
Umm.. documentation? (Score:5, Insightful)
Calling all your variables "pook" or the like may be very cute, but does not help me figure out what the heck the function is supposed to do or why I would ever want to call it. Yes it's a pain. Yes we're all under time deadlines and want to get it working first and go back and document it later. And yes, it WILL bite you in the ass (ever heard of karma? your own memory can go and then you have to decipher your OWN code!).
That said, if you have inherited a code base from someone who ignored the above, go through and generate the documentation yourself. Write flow charts and software diagrams showing what gets called where and why. Derive the equations and algorithms used in each piece and figure out why the constant values are what they are. Finally, start at the main function or reset vector (I do a lot of microcontroller development) and trace the execution path.
Re: (Score:3, Funny)
Osmosis (Score:3, Insightful)
Get the guys who use it to explain what they're trying to do, read the code for a couple of days and then have them show you how they use the application. Then plan on six months to a year to get to the point where you can look at buggy output and know immediately where the failure is occurring. In the mean time just work in it as much as you can and don't try to redesign major parts of it until you know what it's doing.
Last time I had to do something similar... (Score:2)
That is what I would do in your situation, except:
Re: (Score:2)
I don't see dead trees as being any easier for me personally. Too much erasing makes them hard to read, and there was a lot of moving/erasing.
perl and graphviz (Score:2)
I had to do this sort of "unfamiliar code analysis" with an ancient FORTRAN application written by non-software guys in the 1980s. It was some of the worst spaghetti I'd seen in some time.
To make any sense of it, I asked the compiler for a call tree report, and then I fed this through Perl to make a GraphViz "dot" file of it. After a few shuffles, I could start to determine some architecturally related areas and refactor slightly to decouple them into a more clear arrangement of modules. It was still
Don't attempt the impossible... (Score:4, Insightful)
It is unlikely that your job is really to 'grok it all'. Most likely there are specific issues that need to be solved - stop panicking and pick the simplest one on the list and start working on it.
In a similar position to you, I followed Brook's advice to study on the data structures and found it good. Also just running the application under a debugger, inserting breaks in important looking code and then having a look at the call stack when that code was used also proved enlightening. A good debugger also lets you explore the data structures.
When smart-asses tell you "Bill would have fixed that in ten minutes." I recommend replying "I never met Bill, why do you think he left?"
Namgge
Re: (Score:2)
that one works great, Problem is most of the time smart-asses are not the ones doing that, but incredibly stupid managers.
"manager of Marketing, XXX did it in 15 minutes... why are you taking so long?"
The parent's response is perfect for these situations... it shuts them up instantly.
Etags (Score:3, Interesting)
Also, run the program with a debugger and step through it. Or put some print statements in key places and see what it produces.
I find that's all I ever need.
Muhahaha (Score:2)
Now you can hate them too!
hmm. (Score:2)
I find, when in similar situations, start in main() and stroll down the call tree. I also make a beeline for interrupt handlers and pointers - but then I specialize in embedded software so bear in mind that my advice might be as useful as
Understand the design first, then the code (Score:5, Informative)
I'm afraid you've set yourself an almost impossible task. IME, there are no shortcuts here, and it it's going to take anywhere from a few months to a couple of years for a new developer to really get their head around a large, unfamiliar code base.
That said, I recommend against just diving in to some random bit of code. You'll probably never need most of it. Heck, I've never read the majority of the code of the project I work on, and that's after several years, with approx 1M lines to consider.
You need to get the big picture instead. Identify the entry point(s), and look for the major functions they call, and so on down until you start to get a feel for how the work is broken down. Look for the major data structures and code operating on them as well, because if you can establish the important data flows in the program you'll be well on your way. Hopefully the design is fairly modular, and if you're in OO world or you're working in a language with packages, looking at how the modules fit together can help a lot too. Any good IDE will have some basic tools to plot things like call graphs and inheritance/containment diagrams, if not there are tools like Doxygen that can do some of it independently.
If you're working on a large code base without a decent overall design that you can grok within a few days, then I'm afraid you're doomed and no amount of tools or documentation or reading files full of code will help you. Projects in that state invariably die, usually slowly and painfully, IME.
Re: (Score:2)
In general projects in that state have/had
kcachegrind (Score:2)
Look at doxygen/umbrello (Score:3, Informative)
http://www.stack.nl/~dimitri/doxygen/ [stack.nl]
and:
http://uml.sourceforge.net/index.php [sourceforge.net]
These tools allow you to 'visualize' a codebase in several very helpful ways.
One important way is to generate connection graphs of all functions.
These images can look like a mess, or a huge rail yard with hundreds of connections.
The modules, libraries, or source files that are a real jumble of crossconnected lines are a clear indication of where to start clean up activities.
Good luck!
Wait 'till you get to reading the specs... (Score:3, Interesting)
They'll be out of date, full of inconsistencies and incomplete.
Then you'll be reading the code only to discover that people's idiosyncrasies and personalities definitely affects their coding styles. (There's even some gender bias where women tend to set a lot of flags [sometimes quite needlessly] and decided what to do later in the execution while men code as if they knew where they were going all the time, just that when they get there, they're missing some piece of information or other.)
If you read code developed by a whole team of people, you'll get to know them, intimately.
Good luck. You'll be at the bar in no time... I kept the stool warm for you.
If there's an online component (Score:2)
might help.
Its a technique I used successfully, wherever the client was, whatever the client was up to and with whatever staff was on hand. Its domain independent too.
Enjoy.
The Classics (Score:2)
The last time I had to do this (with no documentation, meaningful code comments, or engineering support - no voice option!) it was in a mixed-language code base too.
My tools of choice were:
* etags - like ctags, but supporting pretty much any block-structured language. So navigating from Delphi code into C# code actually worked.
* vim - reads etags files, and of course it is my editor of choice.
* gre
The Slashdot attitude (Score:3, Insightful)
A few years back I had to maintain a large module written in C#. I had about 200K lines of code, 50 classes, zero documentation, zero comments, zero error logging support, and I was expected to find and fix bugs and add functionality the day after the module was handled over.
So if you were never in this position, just STFU. Yeah, the code is there, but is this flag for? Is this part really used, or is obsolete? What are the side-effects of using that method? And so on...
Eventually, I learned it, especially after some intensive debugging sessions, but it was frustrating to say the least. I would have loved to have some aiding tools.
Where be dragons? (Score:2, Informative)
Reverse Engineering Tools (Score:2)
I also second the recomme
Explain the code to someone else. (Score:2)
One technique I've found helpful when confronted with something to big, ugly and important to rewrite....
Find someone, anyone, who will sit in a room with a PC and projector and you explain what the code does to them, in detail.
If you need to diagram, use a whiteboard, Rose is useless. You'll wind up with a huge pile of ineffable UML if you try t
HTML based cross reference (Score:3, Interesting)
ctags *
gtags
htags -Fan
It will create a ~\HTML folder with all the function/variables cross-referenced. Open the file index.html or mains.html in your browser. If your not running Linux, I think these utilities are included in cygwin http://www.cygwin.com/ [cygwin.com]
Enjoy,
Browse-by-Query (Score:3, Informative)
Browse-by-Query [sourceforge.net]-- it won't help with C/C++(sorry for the original questioner), but it will handle Java or C#.
It dumps the code into a database and lets you query it to find the relationships.
I'm biased, of course, but I've found it's just the thing to understand how a particular piece of functionality in an unfamiliar code base fits into the big picture.
Headers (Score:2)
Use UML, and focus on the interfaces (Score:3, Informative)
I recommend focusing on all interface classes first. This can give you a remarkably sane picture of a system, and will help you divide up the code into more conceptually meaningful chunks.
The tool I use is Enterprise Architect [sparxsystems.com], which does quite a lot of heavy lifting yet is still inexpensive enough for me to own a personal copy.
Solution (Score:5, Funny)
Error 'Format Conversion Error, converting from Y2K to Z2L' added to module x1
Error 'Out of Memory Banks' added to module x2
Error 'Object Expected; found adjective instead' added to module x3
Error 'bitbucket 95% full; please empty' added to module x4
Added 1,000,042 to some random value in module x5
Added 5,555,555 to some random value in module x6
Not only will you learn about the code, you'll make a great impression on your boss, when, within minutes, you are able to resolve some mysterious problem that has never happened before.
More than tools (Score:5, Informative)
Feathers, Michael. Working Effectively with Legacy Code [amazon.com], Chapter 16 especially.
Spinellis, Diomidis. Code Reading: The Open Source Perspective [amazon.com], Chapter 10 lists some tools for you.
My own thoughts now. First, don't trust the comments, they are probably outdated. Second, if it's a big code base, forget the debugger. Write some little unit test cases that exercise the sections of code you need to understand, and assert what you think the code is supposed to do.
Finally, unless you are cursed with a codebase which is not kept in version control (in which case, ugh, time to start the jobhunt up again maybe), then take a look at the revision history. See what changes have been made to the area you are working on. With luck, someone will have put in a revision message that points you towards greater understanding of why a change was made, which will in turn nudge you towards knowing the purpose of the section of code that was change.
I had a pile of C++ dropped in my lap 2 years ago. (Score:3, Informative)
I've since added both cscope [sourceforge.net] and freescope [sourceforge.net], as well as the old Red Hat Source Navigator [sourceforge.net] for good measure.
Source Insight (Score:3, Informative)
Shameless plug for CodeSurfer (Score:3, Interesting)
You can browse your code, following dependences and definitions. You can also construct queries, do isolate what statements can affect a particular variable, and a bunch of other tricks based on static analysis. There's a programming interface too.
Other good ways to get your head around code (speaking as a software engineer, rather than a guy promoting his company):
Re: (Score:3, Insightful)
Re:How / why did you get the job... (Score:5, Insightful)
Re: (Score:2)
I started at one company, and they had functions that were 1600 lines long, with gotos.
Not easy to understand, and very complex.
Re:How / why did you get the job... (Score:5, Funny)
I used to work at a company with a lot of Pascal and C code... It was extremely common (as in, all but a few) for programs to be written entirely in one code file. These files would go on for 20,000 lines or more. So many lines in fact that after the compiler had imported the header files at the top of the file that they would be over 65,000 lines long and the debugger would crap out because it had exceeded the int that it used for line number counting.
Sadly this isn't a joke.
Re: (Score:3, Insightful)
Yes, it's hard to understand questions when you don't understand the language.
I'm sure you can find some remedial English classes if you look.
Re: (Score:2)
Re: (Score:2, Insightful)
Re: (Score:2)
Here is a useful bit of vocabulary for explaining why this is so: technical debt [wikipedia.org].