我正在尝试在codeblocks中调试头文件。我尝试了一些选项,如“运行到游标”和将断点放在头文件中,但它不会停在那里并通过那里。 我怎样才能在其中调试.h文件? 如果您需要任何信息,请发表评论。我会提供信息。
答案 0 :(得分:1)
调试器在编译完程序后执行你的程序(并且编译器已执行 指示将调试信息插入已编译的程序中)。它可以让你暂停 在代码中设置的断点处执行,但是只能在断点处暂停 您已将断点设置为程序在运行时到达的某些可执行代码行。 如果您在不是可执行代码的某行上设置断点,或者在 可执行的某行中设置断点 但程序永远不会到达,那么调试器永远不会到达那个断点。
看看这个玩具C程序并考虑每个地方 A ,..., I 你可以在哪里设置一个 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;
}
A处的断点?
这是一个预处理程序指令。预处理器将其从源中删除 代码到达编译器之前。所以编译器永远不会看到它。所以 调试器对此一无所知。这里没有可执行代码。一个断点 永远不会到达。
B处的断点?
这是一个外部函数声明。它提供了必要的信息
编译器和链接器。但它不是可执行代码。
extern void the_answer_is(void);
不是您的程序可以做的东西。
永远不会达到这个断点。
C处的断点?
这里的故事与 A 相同,只是预处理器删除了
#include
指令并将其替换为(预处理)的内容
foo.h
。永远不会达到这个断点。
D处的断点?
此行是全局静态初始化。它在编译时完成, 在程序运行之前。没有可执行代码。永远不会达到这个断点。
E的断点?
这一行是一个函数入口点,从函数定义开始。
它不是本身可执行代码,但它是某些人的切入点
可执行代码。因此可以达到断点。调试器会
只是&#34;超越&#34;一点点,停在第一个可执行行
功能定义。你的程序将在这里找到一个断点如果这个函数,the_answer_is
在执行中的某个时刻被调用。
F处的断点?
此行定义并初始化int i
。这里有一个断点
在与 E 相同的情况下达到,它就是调试器的地方
实际上会停在 E 的断点处。
G的断点?
最有趣的一个。这一行是对函数的调用
在外部库(标准C库)中定义。编译器会看到
extern
在printf
读取标题<stdio.h>
时声明stdio.h
如果您打开extern
并在printf
处设置断点
声明printf
,永远不会达到(与 B 相同)。但
在这里,我们有一个呼叫到printf
,并且呼叫到达。{
与 E 和 F 相同的情况。
所以可以达到这个断点。但是假设你和它达成了它
然后想要在调试器中进入这个对printf
的调用。您
无法获胜。调试器只会跨过它。 您的计划
已编译有调试信息,但库中有
<stdio.h>
的定义没有。你根本不编译那个图书馆;你刚才
将其与您的计划相关联。没有关于库的调试信息,
并且访问它的源代码,调试器不能进入它;所以
没有按&#39;吨
您可能会认为,如果您可以&#34;进入&#34;
像printf
这样的标题你会找到它的源代码
在那里声明的库函数,比如extern int printf( const char* format, ... );
,你可以
调试它。你不会在那里找到源代码。你会发现的就是
外部声明:
<stdio.h>
stdio
对编译器的作用只是告诉它名称
printf
库函数是什么以及如何调用它们。然后
它可以告诉你是否调用了一个尚未声明或调用它的函数
以错误的方式。它不需要the_answer_is
的源代码,因为它已经编译成了the_answer_is
标准C库,您的程序自动链接。
H点的断点
这是整个程序的入口点,所以这个断点 除非发生灾难性事故,否则将始终到达。就像 E ,调试器将停在下一个可执行行。
我的断点?
始终会拨打此#include
的来电,就像 H 一样。
而且因为我们现在知道{{1}}被调用,我们也知道
将到达断点 E , F 和 G 。
底线:
将断点放在{{1}}指令处是没有意义的 或任何其他预处理器指令。编译器永远不会看到它们; 调试器对它们一无所知。
通常,在C中,将断点放在标题中是没有意义的 文件,因为它们只包含声明和预处理器 指令,而不是可执行代码。 (在C ++中,这是一个完全不同的故事。 C ++标头通常包含可执行代码,您可以放置断点 在他们中。)