Understanding large code [closed] - c++

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
The question of understanding a large code has previously been well answered. But I feel I should ask this question again to ask the problems I have been facing.
I have just started a student job. I am a beginner programmer and just learned about classes two months back. At the job though, I have been handed a code that is part of a big software. I understand what that code is supposed to do (to read a file). But after spending a few weeks trying to understand the code and modify it to achieve our desired results, I have come to the conclusion that I need to understand each line of that code. The code is about 1300 lines.
Now when i start reading the code, I find that, for example, a variable is defined as:
VarType VarName
Now VarType is not a type like int or float. It is a user defined type so i have to go the class to see what this type is.
In the next line, I see a function being called, like points.interpolate(x);
Now i have to go into another class and see what the interpolate function does.
This happens a lot which means even if I try to understand a small part of the code, I have to go to 3 or 4 different classes and keep them in mind all at one time without losing the main objective and that is tough.
I may not be a skilled programmer but I want to be able to do this. Can I have some suggestions how i should approach this?
Also (I will sound really stupid when I ask this) what is a debugger? I hope this gives you an idea of where I stand (and the need to ask this question again). :(

With any luck, those functions and classes should have at least some documentation to describe what they do. You do not need to do know how they work to understand what they do. When you see the use of interpolate, don't start looking at how it works, otherwise you end up in a deep depth-first-search through the code base. Instead, read its documentation, and that should tell you everything you need to know to understand the code that uses it.
If there is no documentation, I feel for you. I can suggest two tips:
Make general assumptions about what a function or class will do from its name, return type and arguments and the surrounding code that uses it until something happens that contradicts those assumptions. I can make a pretty good guess about what interpolate does without reading how it works. This only works when the names of the functions or classes are sufficiently self-documenting.
If you need a deep understanding of how some code works, start from the bottom and work upwards. Doing this means that you won't end up having to remember where you were in some high level code as you search through the code base. Get a good understanding of the low level fundamental classes before you attempt to understand the high level application of those types.
This also means that you will understand the functions and classes in a generic sense, rather than in the context of the code that led you to them. When you find points.interpolate(x), instead of wondering what interpolate does to these specific points with this specific x argument, find out what it does in general. Later, you will be able to apply your new-found knowledge to any code that uses the same function.
Nonetheless, I wouldn't worry about 1300 lines of code. That's basically a small project. It's only larger than examples and college assignments. If you take these tips into account, that amount of code should be easily manageable.
A debugger is a program that helps you debug your code. Common features of debuggers allow you to step through your code line-by-line and watch as the values of variables change. You can also set up breakpoints in your code that are of interest and the debugger will let you know when it's hit them. Some debuggers even let you change code while executing. There are many different debuggers that all have different sets of features.

Try making assumptions about what the code does based on its title. For example, assume that the interpolate function correctly interpolates your point; only go digging in that bit of code if the output looks suspicious.

First, consider getting an editor/IDE that has the following features:
parens/brackets/braces matching
collapsing/uncollapsing of blocks of code between curly braces
type highlighting (in tooltips)
macro expansion (in tooltips or in a separate window/panel)
function prototype expansion (in tooltips or in a separate window/panel)
quick navigation to types, functions and classes and back
opening the same file in multiple windows/panels at different positions
search for all mentions/uses of a specific type, variable, function or class and presentation of that as a list
call tree/graph construction/navigation
regex search in addition to simple search
bookmarks?
Source Insight is one of such tools. There must be others.
Second, consider annotating the code as you go through it. While doing this, note (write down) the following:
invariants (what's always true or must always be true)
assumptions (what may not be true, e.g. missing checks/validations or unwarranted expectations), think "what if"
objectives (the what) of a piece of code
peculiarities/details of implementation (the how; e.g. whether exceptions are thrown and which, which error codes are returned and when)
a simplified call tree/graph to see the code flow
do the same for data flow
Draw diagrams (in ASCII or on paper/board); I sometimes photograph my papers or the board. Specifically, draw block diagrams and state machines.
Work with code at different levels of abstraction/detail. Zoom in to see the details, zoom out to see the structure. Collapse/uncollapse blocks of code and branches of the call tree/graph.
Also, have a checklist of what you are going to do. Check the items you've done. Add more as necessary. Assign priorities to work items, if it's appropriate.
A debugger is a program that lets you execute your program step by step and examine its state (variables). It also lets you modify the state and that may be useful at times too.
You may use a debugger to understand your code if you're not very well familiar with it or with the programming language.
Another thing that may come in handy is writing tests or input data test sets for your program. They may reveal problems and limitations in terms of logic and performance.
Also, don't neglect documentation and people! If there's something or someone that can give you more information about the project/code, use that something or someone. Ask for advice.
I know this sounds like a lot, but you'll end up doing some of this at some point anyway. Just wait for a big enough project. :)

You may basically needs to understand what is the functionality of a function being called at first, then understand what is input and output to that function, for example, if you really needs to understand how interpolate is done, you can then go to the details. Usually, the name of the functions are self-explainable, you can get a feeling about what the function does from its name if the code is well written.
Another thing you may want to try is to run some toy examples to go through the code, you can use some of the debuggers or IDE that can help you navigate through the code. Understanding large-scale code takes time and experience, just be patience.

"Try the Debugger Approach"
[Update : A debugger is a special program that lets you pause a running program to examine the state of program (Variable Values/Which function is running/Who is the parent function etc.,)]
The way I do it is by Step Debugging the code, for the usecase I want to understand.
If you are using an Advanced/Mordern IDE then setting breakpoints at the entry point (like main() or a point of interest) is fairly easy. And from there on just enter into the function you want to examine or overstep the function.
To give you a step by step approach
Setup a break point in the main() methods (entry points) starting expression.
Run the program with debugging active
The program will break at the break point.
Now, if step over until you come across a function/expression that seems interesting. (say, your points.interpolate(x); ) function
Step into the function, and examine the program state like the variables and function stack, in live.
Avoid complex system Libraries. Just Step over/Step out. (Example: Avoid something like MathLib.boringComputaion() )
Repeat until the program exits.
I found out that this way of learning is very rapid and gives you a quick understanding of any complex/large piece of software.
Use Eclipse, or if you cant then try GDB if its C/C++. Every popular programming language has a decent Debugger.
Understand the basic debugging operations like will be a benifit:
Setting-up a breakpoint.
Stopping at a breakpoint.
Examine/Watch Variables.
Examine Function Stack (the hierarchy of function calls)
Single-Step - Stepping to next Line in Code.
Step-Into a function.
Step-Out of a function.
Step-over a function.
Jumping to the next breakpoint (point of interest).
Hope, it helps!

Many great answer have already been given. I thought to add my understanding as a former student (not too long ago) and what I learned to help me understand code. This particularly helped me because I began a project to convert a database I wrote in Java many years ago to c++.
1. **Code Reading** - Do not underestimate this important task. The ability to write code
does not always translate into the ability to read it -- and reading it can be more
frustrating than writing it.
Take your time and carefully discover what each line of the codes does. This will certainly help you avoid making assumptions unless you come across code that you are familiar with and can gloss over it.
2. Don't hesitate to follow references, locate declarations, and uncover definitions of
code elements you are reading. What you learn about how a particular variable,
method call, or class are defined all contribute to learning and ultimately to you
being able to perform your task.
This is particularly important because detective, and effective detective work, are essential parts of being bale to understand the small parts of the code so that you can, in the future, grasp the larger parts with less difficulty.
Others have already posted information about what a debugger is and you will find it is an invaluable asset at tracking down code errors and, I think, helps with code reading, knowledge gain, and understanding so you can be a successful programmer.
Here is a link to a debugger tutorial utilizing Visual Studio and may give you a strong understanding of at least the process at hand.

Related

How to deal with large projects in C++? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
Now that I know some of the basics of C++, I must admit that I still find it very hard to deal with code that others have written in C++. This may inherently be so, as C++ allows for complex object hierarchies that are, or at least to me, very hard to grasp if one is just supplied with a C++ Project without any further comments or instructions.
So my question is more a question to the more experienced C++ programmers among you: how can someone understand a large C++ project written by others?
I easily loose my way and can be lost for weeks, if I try to understand how a large project of, for example, 10,000 lines of code is written. Functions of classes are pointers to functions of different classes that may or may not be overloaded and may or may not be inherited by other classes, etcetera, without ending.
Are there any practical tips that may speed up my ability to read and understand large C++ projects? Is there perhaps a tutorial with such tips? Please, elaborate! :)
I've been programming professionally for some time now, and as such I have repeatedly been handed down codebases written by others before me. Understanding is never easy, especially when the code is inconsistent.
The first thing to realize, though, is that learning your ways in a new codebase is not so different than re-discovering a codebase you had not touched for a while. Thus, whether written by your old-self of others does not matter much; and since you probably manage to cope with re-discovering codebases you had worked on before, you should be able to discover new codebases as well. Don't lose hope.
The second thing to realize is that understanding is a vague term, and there are certainly different degrees. Often times, nobody asks you to understand the ins and outs completely; more likely you will be asked to understand a portion of the codebase in which either there is a bug or some new functionality should be developed. Therefore, as time passes, you will gradually gain an understanding of various portions, and you will inevitably have a deeper knowledge of the portions you worked the most whilst others can be relatively abstract or even completely obscure. It's okay, it's been a long time since human beings stopped trying to learn everything there was to learn.
With that said, there are several axis of understanding you can try:
you should look for architecture: a good thing is to trace the library dependencies (the Makefile/Project should help here) this will give you the coarse technical blocks out of which the application is built. Executables are normally leaves of the dependency trees.
you should look for data-flow: what's the trigger of the application (called directly or as a callback) ? what are the steps followed by this data (roughly, just a sketch). Do not hesitate to focus on a specific narrow usecase and use the debugger to trace things, and do not try to dig too deep at first; just get a feel of things.
There are also other axis that may help gaining some understanding of the domain the application has been written for. An understanding of the domain is useful because it provides you with a key insight on what should happen and it also helps you decipher the comments/function names.
user documentation: what is this used for ? if you can arrange for a demo it is generally very helpful, otherwise maybe you can try playing with it yourself (in a test environment)
tests: what is tested ? what is exposed to the user ?
persistent data: what is serialized ? what is saved in a database ? Persistent data is accessed at some point, so it helps if you understand when it is read/written.
If it is a working product (that runs) and you can "debug" it, start by looking at just one particular feature.
Learn how it is working from the user's point of view (UI, behaviour, inputs, outputs, ...).
Once you know the feature from the outside, just look for the code for that feature (only that feature); the starting point might be a handler for a menu, or from a dialog or a mouse/pointer event.
From there; manually trace the code for one action or sub-feature; skip deep internal libraries (treat them as black box for now) and learn how it works.
Once you know that section of code, dig deeper in libraries API that was called from the upper level code.
Take your time.
Do not try to understand everything at once.
Draw up schematic (pen and paper) of the dependencies (stay high level, no class dependencies at the beginning).
Good luck.
The problem that you are mentioning does not have clear and simple answer. Nevertheless here are some tips:
At the beginning try to randomly remember everything. Names of directories, classes, params of templates, etc. As much as you can. This sounds pointless but still makes sense.
While working with the code always think "Have I looked at this function/param/etc before?" If the answer is yes, spend with this piece of code more. If not, just make basic grasp and go on.
As the time will go on, you will find out that more and more sounds clear and easier to grasp.
It is impossible to give any exact values because size and complexity of projects vary greatly. Do not expect simple and immediate results.
Other points:
You definitely need a source code browser. Spend time in learning how to use it. Good example is http://sourceinsight.com/. This is not my site!!! I do have my own site. I will not mention it here.
If you see a function that is called 500 times, it is 500 times more likely that knowledge about this function will be useful comparing with a function, that is called only once.
The best is to grasp the architecture of the project. Trying to do this it is necessary to remember that project may have no architecture at all.
Studying the code you should remember your task. Typical situation - you need to modify something or fix a bug. If this is so look for the right part of the code and focus your effort on it.

how to control one program from other

I want a little help. I know java and little c++. I have seen trainers for games which can set health of player and spawn cars etc. I want to make something similar to that.
For example we have minesweeper running. when i run my java program and click on a button it should call minesweepers function and minesweeper game should show that i won.
So my question is how to establish a connection or something to another program running and calling the program's functions by passing arguments. how is it possible. I heard about reverse engineering and downloaded a program called OllyDBG. And a winject dll injector. i donot know what to do. Combining all these how can i make a program. Please give me ideas or codes or resources helpful.
First you need to reverse-engineer minesweeper to find out the memory location of different variables. Remember that you will probably not be able to run minesweeper's functions due to context, but you can inject code on it to run those. You can read memory easily, though.
To inject code, you must assemble it separately, and then write it in the process virtual space.
In windows API there are several functions that allow opening a process and accessing it memory, but you must have privileges for that.
In summary: To do that, the first thing you need to learn is how to disassemble and understand a program. Only then youll figure out how easy minesweeper is to understand.
BTW: minesweeper stores the map raw in memory. A simple memory inspector will allow you to get the map of it.
Well, your starting sentence was:
"I have seen trainers for games which can set health of player and spawn cars etc. I want to make something similar to that."
Here's a very nice reference code that does what you talked about in C++
http://www.codeproject.com/Articles/7468/Game-Wizard
First strengthen your C++ skills and then study what he does there.
A general description would be that the "victim" process memory is search for a certain value.
Usually something that represents a value that you are aware of - for example, number of bullets of your character.
Usually a big list of location in memory is found at first.
But then, you shoot a bullet, and now the list that you previously found (and only it!) is searched for the new value.
Each step discards the "false positive" finds, until in the end you know the location of the variable that you searched for.
After doing this you are able to change it as well.
Now, going to the general topic - this technique is only a specific approach, and while very helpful in some cases, many times you need stronger and different tools.
Here's a very similar question: How can I find the data structure that represents mine layout of Minesweeper in memory?
I personally find IDA to be an amazing tool for reverse engineering and analyzing an application (both statically and dynamically).
In combination with "idapython" (ida binding for python) it feels unstoppable :)
Reverse engineering requires that you have at least basic knowledge of your target machine architecture - for example, x86 instructions.
Search for IDA tutorials to get the hang of it.
There are many "crackme's" floating around, those are challenges to crack (for educational purposes) varying types of application protections.
It will teach you a lot.
You can also search google for "reverse engineering for beginners".
The web has tons of resources on this topic. The amount of information can be intimidating at first, so make sure you find a basic site that helps you to build your skills gradually.
Another important term that you should know is "hooking". While making it yourself will teach you the most, there are libraries that perform this operation for you.
The idea is to gain control over a certain function.
Whenever anyone calls that function, the control is first passed to your code, and you can decide what to do.
For example, you can decide to simply log this call to a file and call the original function,
or you can do more complicated things.
I found http://tuts4you.com/ to contain many useful tutorials and snippets of information.
Oh, and as people said, Java is not your friend in this case.
C/C++/Assembly probably are.
Starting a completely new topic, especially reverse engineering is tricky in the beginning, but I can assure you it's very rewarding.
Edit:
I have a surprise for you:
http://www.uninformed.org/?v=1&a=7
I simply googled reverse engineering tutorial mine sweeper ;)
Good luck :)

How to approach debugging a huge not so familiar code base?

Seldom during working on large scale projects, suddenly you are moved on to a project which is already in maintainance phase.You end up with having a huge code C/C++ code base on your hands, with not much doccumentation about the design.The last person who could give you some knowledge transfer about the code has left the company already and to add to your horrors there is not enough time to get acquainted with the code and develop an understanding of the overall module/s.In this scenario when you are expected to fix bugs(core dumps,functionality,performance problems etc) on the module/s what is the approach that you will take?
So the question is:
What are your usual steps for debugging a not so familiar C/C++ code base when trying to fix a bug?
EDIT: Enviornment is Linux, but code is ported on Windows too so suggestions for both will be helpful.
If possible, step through it from main() to the problematic area, and follow the execution path. Along the way you'll get a good idea of how the different parts play together.
It could also be helpful to use a static code analysis tool, like CppDepends or even Doxygen, to figure out the relations between modules and be able to view them graphically.
Use a pen and paper, or images/graphs/charts in general, to figure out which parts belong where and draw some arrows and so on.
This helps you build and see the image that will then be refined in your mind as you become more comfortable with it.
I used a similar approach attacking a hellish system that had 10 singletons all #including each other. I had to redraw it a few times in order to fit everything, but seeing it in front of you helps.
It might also be useful to use Graphviz when constructing dependency graphs. That way you only have to list everything (in a text file) and then the tool will draw the (often unsightly) picture. (This is what I did for the #include dependencies in above syste,)
As others have already suggested, writing unit-tests is a great way to get into the codebase. There are a number of advantages to this approach:
It allows you to test your
assumptions about how the code
works. Adding a passing test proves
that your assumptions about that
small piece of code that you are
testing are correct. The more
passing tests you write, the better
you understand the code.
A failing unit test that reproduces
the bug you want to fix will pass
when you fix the bug and you know
that you have succeeded.
The unit tests that you write act as
documentation for the future.
The unit tests you write act as
regression tests as more bugs are
fixed.
Of course adding unit tests to legacy code is not always an easy task. Happily, a gentleman by the name of Michael Feathers has written an excellent book on the subject, which includes some great 'recipes' on adding tests to code bases without unit tests.
Some pointers:
Debug from the part which seems more
relevant to the workflow.
Use debug
strings
Get appropriate .pdb and attach the
core dump in debuggers like Windbg
or debugdiag to analyze it.
Get a person's help in your
organization who is good at
debugging. Even if he is new to your
codebase, he could be very helpful.
I had prior experience. They would
give you valuable pointers.
Per Assaf Lavie's advice, you could use static code analyzers.
The most important thing: as you
explore and debug, document
everything as you progress. At least
the person succeeding you would
suffer less.
Three things i don't see yet:
write some unit tests which use the libraries/interfaces. demonstrate/verify your understanding of them and promote their maintainability.
sometimes it is nice to create an special assertion macro to check that the other engineer's assumptions are in line with yours. you could:
not commit their uses
commit their uses, converting them to 'real' assertions after a given period
commit their uses, allowing another engineer (more familiar with the project) to dispose or promote them to real assertions
refactoring can also help. code that is difficult to read is an indication.
The first step should be try to read the code. Try to see the code where the bug is. Follow the code from main to that point ans try to see what could be wrong. Read the comments from the code(if any). Normally the function names are useful. Understand what each function does.
Once you get some idea of the code then you can start debugging the code. Put breakpoints where you don't understand the code or where you think the error can be. Start following the code line by line. Debugging is like sex. Initially painful, but slowly you start to enjoy it.
cscope + ctags are available on both Linux and Windows (via Cygwin). If you give them a chance, these tools will become indispensable to you. Although, IDEs like Visual Studio also do an excellent job with code browsing facilities as well.
In a situation like yours, because of time constraints, you are driven by symptoms. I mean that you don't have time to reconstruct the big picture / design / architecture. So you focus on the symptoms and work outwards, and each time reconstruct as much of the big picture as you need for that particular problem. But do not make "local" decisions in a hurry. Have the patience to see as much of the big picture as needed to make a good quality decision. And don't get caught in the band-aid syndrome i.e. put any old fix in that will work. It is your job to preserve the underlying architecture / design (if there is one, and to whatever extent that you can discover it).
It will be a struggle at first, as your mind "hunts" excessively. But soon the main themes in the design / architecture will emerge, and all of it will start to make sense. Think, by not thinking, grasshoppa :)
You have to have a fully reliable IDE which has a lot of debbugging tools (breakpoints, watches, and the like). The best way to familiarize yourself with a huge code is to play around with it and see how data is passed from one method to another. Also, you can reverse engineer the code so could see the relationship of the classes. :D Good Luck!
For me, there is only one way to get to know a process - Interaction. Identify the interfaces of the process/system. Then identify the input/output relationship (these steps maybe not linear). Once you do that, you can start tinkering at the code with a fair amount of confidence because you know what it is "supposed to do" then it's just a matter of finding out "how it is actually being done". For me though, getting to know the interface (Not necessarily the user interface) of the system is the key. To put it bluntly - Never touch the code first!!!
Not sure about C/C++, but coming from Java and C#, unit testing will help. In Java there's JUnit and TestNG libraries for unit testing, in C# there's NUnit and mstest. Not sure about C/C++.
Read the book 'Refactoring: Improving the Design of Existing Code' by Martin Fowler, Kent Beck, et al. Will be quite a few tips in there I'm sure that will help, and give you some guidance to improving the code.
One tip: if it aint broke, don't fix it. Don't bother trying to fix some library or really complicated function if it works. Focus on parts where there's bugs.
Write a unit test to reproduce the scenario where the code should work. The test will fail at first. Fix the code until the unit test passes successfully. Repeat :)
Once a majority of your code, the important bits that are too complex to manually debug and fix, is under automated unit tests, you'll have a safety harness of regression tests that'll make you feel more confident at changing the existing code base.
while (!codeUnderstood)
{
Breakpoints();
Run();
StepInto();
if(needed)
{
StepOver();
}
}
I don't try to get an overview of the whole system as suggested by many here. If there is something which needs fixing I learn the smallest part of the code I can to fix the bug. The next time there is an issue I'm a little more familiar and a little less daunted and I learn a little more. Eventually I'm able to support the whole shebang.
If management suggests I do a major change to something I'm not familiar with I make sure they understand the time scales and if things a really messy suggest a rewrite.
Usually the program in question will produce some kind of output ( log, console printout, dialog box ).
Find the closest place to your
problem in the program output
Search through the code base and look for the text in that output
Start putting your own printouts, nothing fancy, just printf( "Calling xxx\n" );, so you can pinpoint exactly to the point where the problem starts.
Once you pinpointed the problem spot, put a breakpoint
When you hit the breakpoint, print a stacktrace
Now you can see what players you have and start the analysis of how you've got to the wrong place.
Hopefully the names of the methods on the call stack are more meaningful than a, b and c ( seen this ), and there is some sort of comments, method documentation more meaningful than calling a ( seen this many times ).
If the source is poorly documented, don't be afraid to leave your comments once you have figured out what's going on. If program design permits it create a unit test for the problem you've fixed.
Thanks for the nice answers, quite a number of points to take up. I have worked on such situation a number of times and here is the usual procedure i follow:
Check the crash log or trace log. Check relevant trace if just a simple developer mistake if cannot evaluate in one go, then move on to 2.
Reproduce the bug! This is the most important thing to do. Some bugs are rare to occur and if you get to reproduce the bug nothing like it. It means you have a better % of cracking it.
If you cant reproduce a bug, find a alternative use case, situation where in you can actually reproduce the bug. Being able to actually debug a scenario is much more useful than just the crash log.
Head to version control! Check if the same buggy behavior exists on previous few SW versions. If NOT..Voila! You can find between what two versions the bug got introduced and You can easily get the code difference of the two versions and target the relevant area.(Sometimes it is not the newly added code which has the bug but it exposes some old leftovers.Well, We atleast have a start I would say!)
Enable the debug traces. Run the use case of the bug, check if you can find some additional information useful for investigation.
Get hold of the relevant code area through the trace log. Check out there for some code introducing the bug.
Put some breakpoints in the relevant code. Study the flow. Check the data flows.Lookout for pointers(usual culprits). Repeat till you get a hold of the flow.
If you have a SW version which does not reproduce the bug, compare what is different in the flows. Ask yourself, Whats the difference?
Still no Luck!- Arghh...My tricks have exhausted..Need to head the old way. Understand the code..and understand the code and understand it till you know what is happening in the code when that particular use case is being executed.
With newly developed understanding try debugging the code and sure the solution is around the corner.
Most important - Document the understanding you have developed about the module/s. Even small knitty gritty things. It is sure going to help you or someone just like you, someday..sometime!
You can try GNU cFlow tool (http://www.gnu.org/software/cflow/).
It will give you graph, charting control flow within program.

Visualizing C++ to help understanding it

I'm a student who's learning C++ at school now. We are using Dev-C++ to make little, short exercises. Sometimes I find it hard to know where I made a mistake or what's really happing in the program. Our teacher taught us to make drawings. They can be useful when working with Linked Lists and Pointers but sometimes my drawing itself is wrong.
(example of a drawing that visualizes a linked list: nl.wikibooks.org/wiki/Bestand:GelinkteLijst.png )
Is there any software that could interpret my C++ code/program and visualize it (making the drawings for me)?
I found this: link text
other links:
cs.ru.ac.za/research/g05v0090/images/screen1.png and
cs.ru.ac.za/research/g05v0090/index.html
That looks like what I need but is not available for any download. I tried to contact that person but got no answer.
Does anybody know such software? Could be useful for other students also I guess...
Kind regards,
juFo
This is unrelated to the actual title but I'd like to make a simple suggestion concerning how to understand what's happening in the program.
I don't know if you've looked at a debugger but it's a great tool that can definitely vastly improve your understanding of what's going on. Depending on your IDE, it'll have more or less features, some of them should include:
seeing the current call stack (allows you to understand what function is calling what)
seeing the current accessible variables along with their values
allowing you to walk step by step and see how each value changes
and many, many more.
So I'd advise you to spend some time learning all about the particular debugger for your IDE, and start to use all of these features. There's sometimes a lot more stuff then simply clicking on Next. Some things may include dynamic code evaluation, going back in time, etc.
Have a look at DDD. It is a graphical front-end for debuggers.
Try debuggers in general to understand what your program is doing, they can walk you through your code step-by-step.
Doxygen has, if I recall, a basic form of this but it's really only a minor feature of a much bigger library, so that may be overkill for what you want. (Though it's a great program for documentation!)
Reverse engineering the code to some sort of diagram, will have limited benefit IMO. A better approach to understanding program flow is to step the code in the debugger. If you don't yet use a debugger, you should; it is the more appropriate tool for this particular problem.
Reverse engineering code to diagrams is useful when reusing or maintaining undocumented or poorly documented legacy code, but it seldom exposes the design intent of the code, since it lacks the abstraction that you would use if you were designing the code. You should not have to resort to such things on new code you have just written yourself! Moreover, tools that do this even moderately well are expensive.
Should you be thinking you can avoid design, and just hand in an automatically generated diagram, don't. It will be more than obvious that it is an automatically generated diagram!

How to create good debugging problems for a contest?

I am involved in a contest, and in one event we have debugging questions. I have to design some really good debugging problems in C and C++.
How can I create some good problems on debugging? What aspects should I consider while designing the problems?
My brainstorming session:
Memory leaks of the subtle sort are always nice to have. Mess around with classes, constructors, copy-constructors and destructors, and you should be able to create a difficult-to-spot problem with ease.
One-off errors for array loops are also a classic.
Then you can simply mess with the minds of the readers by playing with names of things. Create variables with subtly different names, variables with randomized (AND subtly different) names, etc. and then let them try and spot the one place where you've mixed up length and lenght. Don't forget about casing differences.
Calling conventions can be abused to create subtle bugs too (like reversing the order of parameters).
Also let's not forget about endless hours of fun from tricky preprocessor defines and templates (did you know that C++ templates are supposedly Turing-complete?) Metaprogramming bugs should be entertaining.
Next idea that comes to mind is to provide a correct program, but flawed input data (subtly, of course). The program will then fail for the lack of error checking, but it will be some time until people realize that they are looking for problems in the wrong place.
Race conditions are often a difficult to reproduce and fix, try to play with multithreading.
Underflows/overflows can be easily missed by casual inspection.
And last, but not least - if you're a a programmer, try remembering what was the last big problem that you spent two weeks on solving. If you're not a computer programmer, try to find one and ask them. I'm a .NET programmer, so unfortunately my experiences will relate little to your requirement of C/C++.
For some simple "find the bug in this source code" excercises, check out PC-lint's bug of the month archive.
In addition to what's above, consider side effects. For example:
// this function adds two ints and returns the sum
int add_em(int &one, int &two)
{
two += one;
return two;
}
As you can see, this code modifies the two variable, although the comment doesn't mention that...
Debugging is a broad scope, and it may be wise to reflect that in your questions. Without going into details, I can see the following categories :
Source-level debugging - no hints
Questions in this category just have source code, without any further hints on what's wrong.
The actual bug can vary quite a lot here: from straightforward logic bugs like buffer overflows and counting errors to mistaken assumptions, via mathematical errors like rounding errors to just mistaken assumptions like assuming a particular endianness or padding.
Source-level debugging - problem stated
Questions in this category have source code, as well as desired versus actual output/behavior.
E.g. "This program should print 42, but instead prints Out of Memory. Why?"
Crashed code
Questions in this category come not just with source code, but also with a crash dump.
I'll add to the answers above that another form of bugs is the incorrect use of some library or API code. Superficially everything looks ok, but there is some caveat (e.g., a precondition or a limination) that one is not aware of. Interactive debuggers are not as effective by themselves in these situations because they don't expose that information to you (it's often hidden in the documentation).
For example, I did in the past a study of this stuff. I gave people code that used (a messaging API in Java), where the error was that the program was getting stuck as soon as you tried to receive a message. Debugging this interactively was almost impossible. They had to manually figure out what was going on, and realize that one of the queues wasn't set up correctly.
These sort of bugs are actually quite common.
Real world debugging would include find synchronization problems and problems between managed/unmanaged boundary, so please consider c/c++/c# as an option.
Or for real fun, consider using just c# and finding memory leaks.
Also, you will need to mention which tools are allowed to be used. On windows, there are literally dozens of debugging tools available.