Getting Help

How to Find Information and Ask for Help


Sometimes you are going to get stuck while working on code. This page gives a short method for working through the road blocks. Going through each step will help you either find the answer or ask the right questions to get moving again quickly.

  1. Narrow the scope of your problem.

    Try to reduce your problem to a set of specific unknowns. Put tests in your code to help locate the precise source of trouble. For example, if you made some changes to PPL and it won't compile, then the issue is obviously erroneous new code. A specific unknown would be something like: "when I try to pass this Cfg by reference, the compiler throws an error for 'cannot convert from type const Cfg', but I don't know why the object is const." Specific unknowns such as this let you and your potential helper spend time fixing the error instead of finding it.

  2. Consider recent events

    If something that used to work is now broken, chances are that recent events played a significant role. If you have this kind of problem, try to identify any possibly significant events that occurred between the last known functional point and now. What did you change in the code? Did any software get updated? Did you update from git? If you did, did you run make reallyreallyclean? Try reverting specific changes in your working copy to see if they are a source of trouble.

  3. Scout the information sources

    See if you can resolve any unknowns by scouring common information sources. Even if you can't, discussing what you find will help others understand your issue when you ask for help. Check the best known relevant reference, plus Google. Here are some good references to look at for various problems:

    Note: some of these sources are very long! Don't waste your time scrolling around: get used to using the find command (Ctrl+F) to jump straight to the content you need. Use the forward slash command / to do the same in vim.

    • For PPL questions, our internal documentation is the primary resource. It is generated every time you compile. Find it in ppl/docs/Doxygen/html/. Open index.html. You can also try to find example code in the trunk. If you are looking for a specific string of text (such as AddVertex), try searching src/ with grep -r (see the short grep tutorial below if needed).
    • For compiler errors, first try to examine the line of code where the first error occurred. If you can't find a problem, Google the error message and see what you find. Stack Overflow is also highly recommended for this.
    • For general programming questions/troubleshooting, Stack Overflow is a reliable resource. For more specific information...
    • For linux commands, type man command in the console to get the man pages. This is part of a standard system reference in linux.
    • For Parasol systems questions (like how do I edit my web page, or how do I access lab resources remotely), check the this document.
    • For CS questions (like how do I print), check the Engineering IT site.
    • The library's Computer Science Research Resources has links to several journal and conference databases. If visit the guide from campus, you can get free access to many research papers through the library site.
  4. Search the source code

    If the documentation is not sufficient, the next step is to search for examples in the trunk. The tools for doing this are grep and find.

    1. Linux has many handy functions for working with files in specific ways. One such tool that is highly useful in programming is grep: grep is a tool for matching text strings and regular expressions in files.
    2. Let's say I'm working on a new piece of code that needs to make use of a LocalPlanner. I check the documentation and find that IsConnected is one of a LocalPanner's main methods. To find an example of that in the trunk, I could try to guess where it might be, or I could go to src/ with my terminal and use grep to get the definitive list:
      grep -r -n "IsConnected" .
      This will generate a bunch of lines that look like this...
      ./LocalPlanners/AStar.h:38: virtual bool IsConnected(
      ./LocalPlanners/AStar.h:55: virtual bool IsConnectedOneWay(
      ./LocalPlanners/AStar.h:109: AStar<MPTraits>IsConnected(
      ...
      ...which indicate that grep found the line of text virtual bool IsConnected( which contained the search term IsConnected in line 38 of the file AStar.h in the LocalPlanners/ directory.
    3. The . here represents the current directory, but you could replace it with some other path, such as ~/Downloads to search your downloads directory. The -r indicates recursive, which tells grep to investigate all sub-directories of .. The -n instructs grep to print out the line number of each matching line, which you can later jump straight to in vim by typing the line number followed by gg (for example, 38gg).
    4. Using two terminals, you can rapidly find and inspect various instances of your search terms: open two terminals (or two tabs in one terminal) and get to src/ in both of them. In one terminal, grep for a term, say for example IsConnected as above. In the second terminal, open the first result (shown above) in vim with the command vi MPLibrary/LocalPlanners/AStar.h. Then jump to the line numbers you are interested in from the grep results with gg: 38gg, 55gg, 109gg, etc. This is an effective way to look at a large volume of example code quickly, and can spare you a lot of time by getting linux to find things for you.
    5. If you know the name of a file, but don't know where it's located, then find is your tool. Let's say I wanted to find the file AStar.h. If I had no clue where it was, I could search my entire research directory with one command:
      find /research/me/ -name "AStar.h"
      If you checked out PPL to the directory /research/me/PPL/, then find would print:
      /research/me/PPL/simulator/src/MPLibrary/LocalPlanners/AStar.h
      If you have any other files named AStar.h, then find will print those too. This is a great tool because you don't have to remember where anything is so long as you remember how to find it.
  5. Handling segmentation faults

    If you are tracking down a seg fault, gdb (the GNU debugger) is your tool. The debugger allows you to run your program in a sort of sandbox. Using the debugger, you can stop, start, and step program execution one line at a time, view a backtrace (i.e. the list of function calls that arrived at the current state), as well as examine data.

    To use GDB, the basic paradigm is to load your program into the debugger, set any breakpoints you want, run the program, then search for the cause of your problem.

    Starting Your Program in GDB: To run your program in gdb, the first step is to ensure that you compiled with debug symbols. In PPL, this is done by setting a flag in the Makefile. Ensure that the debug option in src/Makefile is set to 1. If you had to change this setting, be sure to rebuild the entire library (i.e. make reallyreally clean, make).

    Once your program is compiled with debug symbols, to run your program in gdb use:

    gdb <program_name>

    To run your program with arguments instead use:

    gdb --args <program_name> <program_arguments>
    gdb --args ./ppl -f Examples/CfgExamples.xml

    Once your program is loaded, execution can be started with:

    run

    This will run your program to completion because we haven't yet told gdb to stop anywhere. This can be useful to find where exactly a segfault is (more on that later).

    Controlling Execution: Gdb can run your program in two ways, either continuously, where each subsequent instruction is run after the previous finishes (i.e. like your program normally runs), or one instruction at a time, stopping after each line. Normally, what you want to do is run your program continuously until you get to the problem area, at which point you want to step through and see exactly what is happening. To run the program until a certain point (or condition) is met, breakpoints are used. To set a breakpoint at a certain line number use:

    break <filename>:<line_number>
    break SamplerMethod.h:42

    With a breakpoint set, the code will run until a breakpoint is hit, at which point execution will stop and you can enter more commands. You should also note that many breakpoints can be set, and set breakpoints can be removed. If you try to set a breakpoint in a file and gdb asks about a a future library load, it means you either mispelled something, or did not compile with debug mode on (see compiling for the debugger above).

    Once the execution has hit a breakpoint, gdb will halt execution and wait for input. At this point, you can examine the program state, step through lines of code, or continue execution. To continuce execution until the next breakpoint, simply use:

    continue

    To step through execution a little at a time, there are two options. Either you can run the entire next line (function calls and all) with next, or you can run the next line stepping into any functions with step. Typically, you want to use next to get where you need to or to skip cumbersome (and usually correct) parts of the code, such as printing or manipulations of standard library data structures. Use step when calling functions for which you want to examine the execution.

    Examining Data: Gdb provides powerful tools for examining data. You can access all data available in the current context (i.e. whatever function you are currently in) using the corresponding variable names. Further, the syntax looks very similar to C++ code. This is done using the print command. Below are a few examples.

    Print a variable in the current context.

    print myVariable

    Print the current object.

    print this

    Print a member variable from the current object.

    print this->m_variable

    Print the return value from a function from the current object.

    print this->MyClassFunction()

    Arguments can also be passed.

    print this->MyClassFunctionWithArg(42)

    The print command can be very useful for tracking down a Null pointer.

    Examining The Stack: Gdb can also show a backtrace of the stack. This will show you a history of the functions that were called to get to the current context. The most recent functions are at the top, and the oldest are at the bottom. The backtrace contains useful information such as what arguments were used to call the function. Note that the bracketed number starting each line is the frame number.

    backtrace

    You can also switch the current context in the backtrace (for example, up a level to a different function).

    frame <frame_number>

    Further GDB Readings: Gdb is a powerful tool with many uses and far too many commands to cover here. For more information in an easily digestable form, take a look at this tutorial. For a complete reference, check out this more complete GDB tutorial.

  • Asking for help

    If you can't find the source of your problem or you think it will take you prohibitively long to fix it, gather up what you have thus far and ask for help. If you went through the short process above, you will be prepared with some essential information:

    • Specific unknowns help you get to the root of the problem quickly
    • Identifying potential causes gives you an idea of where to look further
    • Pre-checking relevant references shows that you have checked for a known solution
    • Discussing attempted resolutions narrows the possible routes forward

    A question primed with these ingredients is likely to receive a good answer. Doing your best to investigate problems to a reasonable extent also improve your troubleshooting skills and prepare you to apply what you learn from others.

    Another important thing to consider is what kind of help to ask for. If you think that you could solve the problem given some resource, ask where to find the resource. Even when asking for help, try to do as much as possible yourself.

    Who should you ask? Start with your direct peers and continue down the list as necessary.

    1. A fellow student (your direct peers)
    2. Experienced undergraduates
    3. Your mentor
    4. Any senior member of the lab