need help with conditional gdb debugging (of C code) - c

I have a C code similar to:
int f() {
for (int i = 0; i < 100; i++) {
scanf flag;
if(flag)
scanf data1;
scanf data2;
}
}
I want to break the execution only when flag == 0. How should I set the breakpoint (using gdb)?

In the gdb console type
b (some_line) if flag == 0
EDIT:
If you can't print flag while stopped at some-line, then either:
- (A) your code is compiled with optimization (likely), or
- (B) you have a buggy compiler
If it's (A), add -O0 in addition to -g3.
If you can print flag, then you have a buggy version of GDB. Try upgrading to current 7.0.1 release.

Related

GDB moves breakpoint to different line

I'm debugging C code running on a MSP430 microprocessor using GDB.
When I set a breakpoint on the line double average = sum / 10; using break 172, it confirms by responding Breakpoint 1 at 0xc01c: file main.c, line 172, but when I continue with c, the code runs until it hits Breakpoint 1, main () at main.c:184.
I wasn't having issues debugging until recently, so I tried reverting everything to the previous version and I still have this issue. I have also tried:
Turning my laptop off and on.
Unplugging and re-plugging every cable related to the microprocessor and its circuit.
Closing and re-opening all terminal windows.
Re-compiling and re-loading my C code into the microprocessor.
Print statements to help debugging aren't an option because the microprocessor can't hold #include <stdio.h>.
Clearing all breakpoints present before setting this one, but none are found.
The code looks something like:
void main(void)
{
OtherMethod();
while(1)
{
int sum = 0;
for(int i = 0; i < 10; i++)
{
sum += i;
}
double average = sum / 10; // Line 172
}
}
void OtherMethod(void)
{
P1DIR |= LED1 + LED2; // Line 184
}
Other information that might be helpful is that I can successfully set a breakpoint on the line sum += i;.
Any ideas are appreciated.
If you compile with optimization, several "strange" things might happen, see your compiler's documentation. This might lead to statements being removed or re-arranged, and when debugging, surprising behaviour.
To debug a program "by the line", compile without optimization.
Or live with the surprises; it's a source of delight, in any case.

Im having problems using stdin and NULL in eclipse

Here is my code that I am having issues with. The goal of the program is to scan in a bunch of doubles and perform some simple statistical operations on them. The line I am having the issue with is the fgets(). I have included the stdio.h, it's just not showing up in the code. My actual question is where are the stdin and NULL giving me issues when I though they were part of the language? The exact error I am getting is that both Symbol stdin and NULL could not be resolved.
/*
* simpleStats.c
*
* Created on: Sep 17, 2018
* Author: David Liotta
*/
#include <stdio.h>
#define BUFSIZE 256
int main(){
double n, max, min, sum, mean;
char line[BUFSIZE];
int numsRead = 0;
int numOfItems = 1;
n = -1;
max = n;
min = n;
sum = n;
while(n != 0 && fgets(line, BUFSIZE, stdin ) != NULL){
numsRead = sscanf(line, "%f", &n);
if(numsRead == 1 && n != 0){
numOfItems++;
if(n > max)
max = n;
if(n < min)
min = n;
sum = sum + n;
}
if(numsRead == 0)
printf("Bad input\n");
}
mean = sum / numOfItems;
printf("# of items: %i", numOfItems);
printf("\nSum: %f.3", sum);
printf("\nMax: %f.3", max);
printf("\nMin: %f.3", min);
printf("\nMean: %f.3", mean);
}
This code should compile. I suspect something might be wrong with your development environment.
Since you're running Eclipse, I'm assuming that your compiler is GCC. I may be wrong though.
Try to locate your compiler executable, and run the compilation by hand:
gcc -Wall -o simpleStats simpleStats.c
or, if you're on Windows:
gcc.exe -Wall -o simpleStats.exe simpleStats.c
You may have to specify the full path to gcc.exe, (depending on your environment, it might even be called something else; you may be able to retrieve the full path from the console window in Eclipse).
Pay close attention to the output. Copy/paste the full output verbatim in your original post if you can (do not rephrase the warnings / error messages).
I seldom use Eclipse, but with most IDEs you get to chose what kind of project you want to create. Make sure you selected something like "console application", the error you're referring to (stdin not being resolved) may suggest a linker error. Again, it's hard to tell without the exact GCC output.
A couple more things to check:
make sure your compiler and its dependencies are properly installed,
make sure that this compiler is targeted at Windows (or whatever OS you use), not at some exotic embedded platform,
most development environments come with a bunch of sample projects, see if you can build one.
The problem I was having ended up being the compiler not correctly reading the code. I used a different compiler, and with some minor syntax changes, the code worked fine.

How can i detect "out of bound error" in C program with GDB?

I wrote this program in C, adding an intentional error on purpose.
The program calculates the sum of 5 numbers entered by the user, and displays the result on the screen.
I compiled it with "gcc -Wall -Wextra -Werror -ansi -pedantic -g" and works fine.
But it has an error.
In the last repetition of the cycle, the program evaluates a[N], which is not defined!
I'd like to know how to spot this kind of error using GDB
When i use "set check range on" i get this messange "warning: the current range check setting does not match the language." and nothing happens...
This is the code to debug:
#define N 5
#include <stdio.h>
void read(float*);
int main(void) {
float a[N], s;
int i;
printf("Enter %d numbers: ", N);
read(a);
i = -1;
s = 0;
while (i != N) {
i = i + 1;
s = s+a[i];
}
printf("The sum is : %.2f \n", s);
return 0;
}
void read(float*a) {
int n = 0;
while (n!=N) {
scanf("%f",&a[n]);
n++;
}
}
I think this is your problem:
while (i != N) {
i = i + 1;
s = s+a[i];
}
N is defined as 5, so when i is 4, the condition is true. i is then incremented to 5, and s += a[i]; is executed. Just use a for loop instead, or use do {} while:
for (i=0;i<N;++i)
s += a[i];
//or
i = 0;
do {
s += a[i];
} while (++i != N);
Either way. Personally, I find the for loop more readable
To answer your question (using gdb):
You've compiled using the -g flag, so run `gdb compiled_file_name
In gdb, set a break-point in the while loop (b <line-nr> [condition])
start the program (run)
use step or next to step through the code
use p i to check the value of i every time you hit the while condition, and every time you use i as offset (a[i])
For more details, docs for gdb are available. It takes some time, but it's well worth it. gdb is an excellent debugger
The answer to this particular error is that the loop increments i and then accesses a at index i, without an intervening check. So when i equals N - 1 when it starts the loop, it's incremented to N and used in the array.
In general, gcc's -fsanitize=bounds option should be helpful for these errors.

Using gcc to compile a C program

I am following an example from CUNY and I have never done anything with C before so I probably don't know what I am doing.
Consider the program below.
Do I need a shebang line for C code written in emacs?
When I go to compile using the line gcc -g -o forwardadding forwardadding.c
I am hit with the message:
forwardadding.c:9:17: error: expected expression before ‘<’ token
Once I get the code compiles, I can use gdb to debug and run the code corrrect?
The code:
#include <stdio.h>
#include <math.h>
main()
{
float sum, term;
int i;
sum = 0.0;
for( i = 1; < 10000000; i++)
{
term = (float) i;
term = term * term;
term = 1 / term;
sum += term;
}
printf("The sum is %.12f\n", sum);
}
No shebang is needed. You could add an Emacs mode line comment.
The for loop should be:
for (i = 1; i < 10000000; i++)
Your code is missing the second i.
Yes, you can use GDB once you've got the code compiling.
You'd get a better answer to the mathematics if you counted down from 10,000,000 than by counting up to 10,000,000. After about i = 10000, the extra values add nothing to the result.
Please get into the habit of writing C99 code. That means you should write:
int main(void)
with the return type of int being required and the void being recommended.
You need to put a variable in the for loop for a complete expression (which is probably line 9...)
for( i = 1; < 10000000; i++)
change to this
for( i = 1; i < 10000000; i++)
You are missing an an i. Just correct that as Jonathan Leffler has suggested and save your file. Open your terminal and just use this to compile your code gcc your_file_name.c and your code compiles next to run the code that just compiled type ./a.out and your program runs and shows you the output.

Debugging C code with gdb

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
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.
From gdb, do break main, then run.
From there, next or step until you find where you went wrong.

Resources