Awais Hussain
Awais Hussain

Reputation: 442

Debugging header files in codeblocks

I am trying to debug header file in codeblocks. I have tried some options like "run to cursor" and by putting breakpoint in header file but it doesn't stops there and passes through there. How can I debug .h file in it? If you need any information, just comment. I'll provide the info.

Upvotes: 1

Views: 3454

Answers (1)

Mike Kinghan
Mike Kinghan

Reputation: 61337

The debugger executes your program, after it has been compiled (and the compiler has been instructed to insert debugging information into compiled program). It lets you pause the execution at breakpoints you have set in the code, but it can only pause at a breakpoint if you have set the breakpoint at some line of executable code that the program reaches at some point when it runs. If you set a breakpoint at some line that isn't executable code, or at some line that is executable but the program never reaches, then the debugger will never reach that breakpoint.

Look at this toy C program and consider each of the places A,...,I where you might set a breakpoint in Code::Blocks:

foo.h

#ifndef FOO_H
#define FOO_H

#define FORTY_TWO 42  /* A */
extern void the_answer_is(void); /*B*/

#endif

foo.c

#include "foo.h" /* C */
#include <stdio.h>

static int forty_two = FORTY_TWO; /* D */

void the_answer_is(void) /* E */
{
    int i = forty_two; /* F */
    printf("The answer is...%d\n",i); /* G */
}

main.c

#include "foo.h"

int main(void) /* H */
{
    the_answer_is(); /* I */
    return 0;
}

Breakpoint at A?

This is a preprocessor directive. The preprocessor removes it from the source code before it gets to the compiler. So the compiler never sees it. So the debugger knows nothing about it. There is no executable code here. A breakpoint will never be reached.

Breakpoint at B?

This is an external function declaration. It provides necessary information to the compiler and the linker. But it's not executable code. extern void the_answer_is(void); is not something your program can do. This breakpoint will never be reached.

Breakpoint at C?

The story here is the same as A, except that the preprocessor removes the #include directive and replaces it with the (preprocessed) contents of foo.h. This breakpoint will never be reached.

Breakpoint at D?

This line is a global static initialization. It's done at compiletime, before your program ever runs. No executable code. This breakpoint will never be reached.

Breakpoint at E?

This line is a function entry point, beginning a function definition. It is not itself executable code, but it is the entry point of some executable code. So a breakpoint here can be reached. The debugger will just "overshoot" a little and stop at the first executable line in the function definition. Your program will get to a breakpoint here if the function, the_answer_is gets called at some point in execution.

Breakpoint at F?

This line defines and initializes int i. A breakpoint here will be reached in the same circumstances as E, and it is where the debugger would actually stop for a breakpoint at E.

Breakpoint at G?

The most interesting one. This line is a call to a function that is defined in an external library (the Standard C Library). The compiler will have seen the extern declaration of printf when it read the header <stdio.h> If you had opened up stdio.h and put a breakpoint at the extern declaration of printf, it would never be reached (same as B). But here we have a call to printf, and that call be reached in the same circumstances as E and F.

So this breakpoint can be reached. But suppose you reach it and you then want to step into this call to printf in the debugger. You won't be able to. The debugger will just step over it. Your program has been compiled with debugging information, but the library in which printf is defined has not. You don't compile that library at all; you just link it with your program. Without debugging information about the library, and access to its source code, the debugger can't step into it; so it doesn't.

You might be under the impression that if you could "step into" a header like <stdio.h> you would find the source code of the library functions that are declared there, say printf, and you could debug into it. You wouldn't find the source code there. All you would find is the external declaration:

extern int printf( const char* format, ... );

The role of <stdio.h> for your compiler is just to inform it what the names of the stdio library functions are and how they should be called. Then it can tell you if you call a function that hasn't been declared or call it in the wrong way. It doesn't need the source code of printf because its already compiled in the Standard C Library, which your program is automatically linked with.

Breakpoint at H?

This is the entry point of your whole program, so this breakpoint will always be reached, barring catastrophic accidents. Just as for E, the debugger will stop at the next executable line.

Breakpoint at I?

This call to the_answer_is will always be reached, just like H. And because we now know that the_answer_is gets called, we also know that the breakpoints E,F and G will be reached.

Bottom line:

  • It is pointless to put breakpoints at #include directives or any other preprocessor directives. The compiler never sees them; the debugger knows nothing about them.

  • In general, in C, it is pointless to put breakpoints within header files, because they just contain declarations and preprocessor directives, not executable code. (In C++, it is quite a different story. C++ headers usually contain executable code, and you can place breakpoints in them.)

Upvotes: 5

Related Questions