简体   繁体   English

用gdb调试C代码

[英]Debugging C code with gdb

This is a homework assignment, I just want help with gdb, not specific answers. 这是一个家庭作业,我只是想要gdb的帮助,而不是具体的答案。

I have no experience with gdb whatsoever and little terminal experience. 我没有任何gdb的经验和很少的终端体验。 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. 我在网上跟随了一个简单的示例,使用gdb调试了一些代码,但是在示例gdb中,指出了在运行代码时发生了问题。 When I try to mimic the process for this assignment gdb doesn't say anything. 当我试图模仿这个任务的过程时,gdb没有说什么。 I am still somewhat new to C, but I can see problems when I look at the code and gdb isn't saying anything. 我对C仍然有点新,但是当我查看代码并且gdb没有说什么时,我可以看到问题。

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. 假设文件名为test.c,在终端我输入gcc test.c并且它给了我一个警告,因为printf()在那里但#include <stdio.h>不是,这很好,因为它应该是错误。

It also produces a.out and if I run it in the terminal with ./a.out nothing happens. 它也会产生一个a.out,如果我在终端中使用./a.out运行它没有任何反应。 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. 如果我键入gdb ./a.out然后运行它只是告诉我程序正常退出。

Can someone point out what I have to do to make gdb point to the errors please? 有人可以指出我要做什么让gdb指向错误吗?

// 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 . 如果编译器检测到任何约束违规,则要求编译器(C标准)发出错误。 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. 如果添加-Wall-Wextra选项,则编译器将为您提供更多错误诊断。 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). 如果启用优化( -O0-O3设置不同的优化级别),编译器可能能够检测到更多错误,但是如果要在调试器中单步执行,则可能需要跳过优化,因为优化程序将使调试器更难向您显示相关的源代码行(有些可能会重新排序,有些可能会被淘汰)。

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. 因此,正如Brian所说,您需要设置断点并单步执行程序。 And, as jweyrich says, you need to compile the program with -g to add debugging symbols. 而且,正如jweyrich所说,您需要使用-g编译程序以添加调试符号。

You can inspect variables with print (eg. print Argc will tell you how many command-line arguments were on the run line). 您可以使用print检查变量(例如, print Argc会告诉您run行上有多少命令行参数)。 And display will add variables to a list that is displayed just before each prompt. 并且display会将变量添加到在每个提示之前显示的列表中。 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. 如果我在Insert通过for循环调试,我可能会display Jdisplay Y[J]next ,然后点击输入很多次来观察计算进度。

If your breakpoint is deeply nested, you can get a "stack dump" with backtrace . 如果断点是深层嵌套的,则可以使用backtrace获得“堆栈转储”。

next will take you to the next statement (following the semicolon). next将带您进入下一个语句 (分号之后)。 step will take you into function calls and to the first statement of the function. step将带您进入函数调用和函数的第一条语句。 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; 请记住:如果您单步执行某个函数并进入“ return”语句,请使用step在调用语句中输入下一个函数调用;否则,请执行以下step use next at the return to finish the calling statement (and just execute any remaining function calls in the statement, without prompting). 在返回处使用next来完成调用语句(并仅执行该语句中所有剩余的函数调用,而不会提示)。 You may not need to know this bit just yet, but if you do, there you go. 您可能还不需要知道这一点,但是如果您知道,就可以了。

From gdb , do break main , then run . gdb ,先break main ,然后run

From there, next or step until you find where you went wrong. 从那里, nextstep ,直到你找到你在哪里错了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM