2

This is a homework assignment, I just want help with gdb, not specific answers.

I have no experience with gdb whatsoever and little terminal experience. I followed a simple example online to debug some code using gdb but in the example gdb pointed out that a problem happened when it ran the code. When I try to mimic the process for this assignment gdb doesn't say anything. I am still somewhat new to C, but I can see problems when I look at the code and gdb isn't saying anything.

Say the file is named test.c, in the terminal I type gcc test.c and it gives me a warning because printf() is there but #include <stdio.h> is not, which is good because that is supposed to be wrong.

It also produces a.out and if I run it in the terminal with ./a.out nothing happens. The terminal just is ready for my next input with no messages. If I type gdb ./a.out and then run it just tells me the program exited normally.

Can someone point out what I have to do to make gdb point to the errors please?

// insertion sort, several errors

int X[10],  // input array
    Y[10],  // workspace array  
    NumInputs,  // length of input array
    NumY = 0;  // current number of 
               // elements in Y

void GetArgs(int AC, char **AV) {
    int I;
    NumInputs = AC - 1;
    for (I = 0; I < NumInputs; I++) X[I] = atoi(AV[I+1]);
}

void ScootOver(int JJ) {
    int K;
    for (K = NumY-1; K > JJ; K++) Y[K] = Y[K-1];
}

void Insert(int NewY) {
    int J;
    if (NumY = 0) { // Y empty so far, 
        // easy case
        Y[0] = NewY;
        return;
    }
    // need to insert just before the first Y
    // element that NewY is less than
    for (J = 0; J < NumY; J++) {
        if (NewY < Y[J]) {
            // shift Y[J], Y[J+1],... rightward 
            // before inserting NewY
            ScootOver(J);
            Y[J] = NewY;
            return;
        }
    }
}

void ProcessData() {
    // insert new Y in the proper place
    // among Y[0],...,Y[NumY-1]
    for (NumY = 0; NumY < NumInputs; NumY++) Insert(X[NumY]);
}

void PrintResults() {
    int I;
    for (I = 0; I < NumInputs; I++) printf("%d\n",Y[I]);
}

int main(int Argc, char ** Argv) {
    GetArgs(Argc,Argv);
    ProcessData();
    PrintResults();
}

Edit: The code is not mine, it is part of the assignment

5
  • "if I run it in the terminal with ./a.out nothing happens". After reading your code, that's exactly what I'd expect to happen. Try entering "./a.out 3 2 1" and see what happens. Commented Jan 24, 2013 at 5:31
  • Try it and see! :) Be sure to put spaces between the numbers. Then try putting different numbers in - but don't put in more than ten numbers. Commented Jan 24, 2013 at 5:37
  • I did not know argc and argv[] took the arguments passed to the program... that was one lucky Google search. I always ignored those arguments Commented Jan 24, 2013 at 7:08
  • It looks to me like this program is intended to take a list of up to 10 integers entered as command-line arguments, sort them in ascending order, and print the sorted list. It also looks to me like it has a bug. Commented Jan 24, 2013 at 19:13
  • Yeah, that is the point, it has a few bugs Commented Jan 24, 2013 at 19:55

2 Answers 2

7

There are different kinds of errors. Some can be detected by programs (the compiler, the OS, the debugger), and some cannot.

The compiler is required (by the C standard) to issue errors if it detects any constraint violations. It may issue other errors and warnings when not in standards compliance mode. The compiler will give you more error diagnostics if you add the -Wall and -Wextra options. The compiler may be able to detect even more errors if you enable optimizations (-O0 through -O3 set different levels of optimization), but you may want to skip optimizations if you want to single-step in the debugger, because the optimizer will make it harder for the debugger to show you the relevant source-lines (some may be re-ordered, some may be eliminated).

The operating system will detect errors involving traversing bad pointers (usually), or bad arguments to system calls, or (usually) floating-point division by zero.

But anything that doesn't crash the program is a semantic error. And these require a human brain to hunt for them.

So, as Brian says, you need to set breakpoints and single-step through the program. And, as jweyrich says, you need to compile the program with -g to add debugging symbols.

You can inspect variables with print (eg. print Argc will tell you how many command-line arguments were on the run line). And display will add variables to a list that is displayed just before each prompt. If I were debugging through that for-loop in Insert, I'd probably do display J and display Y[J], next, and then hit enter a bunch of times watching the calculation progress.

If your breakpoint is deeply nested, you can get a "stack dump" with backtrace.

next will take you to the next statement (following the semicolon). step will take you into function calls and to the first statement of the function. And remember: if you're single-stepping through a function and get to the 'return' statement, use step to enter the next function call in the calling statement; use next at the return to finish the calling statement (and just execute any remaining function calls in the statement, without prompting). You may not need to know this bit just yet, but if you do, there you go.

Sign up to request clarification or add additional context in comments.

8 Comments

+1. I'd also recommend compiling with -g3 -O0, so gdb can print filenames, symbols, and source lines. Additionally, I recommend the good habit of always compiling with -Wall -Wextra (and -pedantic when possible).
@jweyrich Thank you. I've incorporated some of that. [Don't want to overload him. :)]
@luserdroog: Cool! :-) Pity I cannot upvote more than once. Though I cannot think of a case where increasing the optimisation level would change (or improve) error detection. Can you elaborate on that, or give any references?
Could you explain step by step how to print Argc please?
Well, it doesn't exist until the program is being run. So do break main, run 2 3 4 5, and print Argc should print 5.
|
2

From gdb, do break main, then run.

From there, next or step until you find where you went wrong.

1 Comment

Thank you, that made something appear. I'll play with breaks

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.