调试codeblocks中的头文件

时间:2015-02-21 19:33:32

标签: c header codeblocks

我正在尝试在codeblocks中调试头文件。我尝试了一些选项,如“运行到游标”和将断点放在头文件中,但它不会停在那里并通过那里。 我怎样才能在其中调试.h文件? 如果您需要任何信息,请发表评论。我会提供信息。

1 个答案:

答案 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库)中定义。编译器会看到 externprintf读取标题<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 ++标头通常包含可执行代码,您可以放置​​断点 在他们中。)