C 如何在巨型循环中使用GDB

C 如何在巨型循环中使用GDB,c,linux,debugging,gdb,breakpoints,C,Linux,Debugging,Gdb,Breakpoints,我有下面的循环,我的代码中断,但我不知道它在哪个迭代中确切中断 int n=1000; for (i=0; i<n; i++) { slot = random() % max_allocs; doAlloc = random() % 4; doWrite = writeData; if (!doAlloc || ptr[slot] != NULL) {

我有下面的循环,我的代码中断,但我不知道它在哪个迭代中确切中断

int n=1000;
for (i=0; i<n; i++) {
                slot = random() % max_allocs;
                doAlloc = random() % 4;
                doWrite = writeData;

                if (!doAlloc || ptr[slot] != NULL) {
                        if (ptr[slot] == NULL)
                                ;//assert(Mem_Free(ptr[slot]) == -1);
                        else
                        {
                                printf("I got here \n");
                                printf("mem free ptr slot is %d \n",Mem_Free(ptr[slot]));
                        }
                        free(shadow[slot]);
                        ptr[slot] = NULL;
                        shadow[slot] = NULL;
                }

                if (doAlloc) {
                        size[slot] = min_alloc_size +
                                (random() % (max_alloc_size - min_alloc_size + 1));
                        printf("size[slot] :%d\n", size[slot]);
                        ptr[slot] = Mem_Alloc(size[slot], BESTFIT);
                        printf("ptr slot is %p \n",ptr[slot]);
                        assert(ptr[slot] != NULL);
                        if (doWrite) {
                                shadow[slot] = malloc(size[slot]);
                                int j;
                                for (j=0; j<size[slot]; j++) {
                                        char data = random();
                                        *((char*)(ptr[slot] + j)) = data;
                                        *((char*)(shadow[slot] + j)) = data;
                                }
                        }
                }
        }
int n=1000;
对于(i=0;i请看以下内容:。
您可以使用中断(设置断点)和继续/下一步执行所需操作:

  • 不要忘记使用-g选项编译:gcc-gsource.c
  • gdb./a.out
  • 中断行号
  • 继续下一个(继续到下一个断点)
  • 打印变量(打印变量值)

  • 希望有帮助。

    如果我想在第500次迭代时在第94行设置断点,我应该这样做:

    b 94如果i=500

    一般来说,你会说:


    如果条件

    您似乎对查找中断的迭代挂起了钩,但上面的答案清楚地说明了如何执行此操作

    在GDB中运行您的程序,等待代码崩溃(此时GDB将抓取它),然后在GDB提示符下使用
    print i
    打印索引变量的值,计算出它在哪个迭代中崩溃

    编辑:好的,我想我明白了。当你说代码“中断”时,你的意思是它以允许继续执行的方式中断:它没有崩溃,GDB也不会自动捕获它

    在这种情况下,无法确定要在何处设置断点。您根本不知道问题何时发生。如何确定程序正在中断?是否有任何变量可以打印的值以显示中断发生的时间?如果是,您可以让GDB在每次迭代期间打印值(而不是将调试直接写入代码)

    您可以使用
    命令
    选项执行此操作。下面是一个如何在线程中执行此操作的示例


    在每次迭代中,打印
    i
    的值,以及用于跟踪破损的变量的值。这将为您提供破损发生的迭代,您可以返回并在正确的位置设置断点。

    您如何知道代码正在“破损”首先?通常是因为某个变量突然出现了一个您不期望的值。在这种情况下,您可以设置一个观察点而不是断点,并且只有当该变量超出预期时才会中断

    例如,使用此程序:

    #include <stdio.h>
    
    int main(void) {
        int b = 0;
        for ( int i = 0; i < 20; ++i ) {
            b += 5;
        }
        return 0;
    }
    
    在这里,我们可以看出
    b
    i
    4
    时,即在循环的第五次迭代时,超过了
    20
    。您可以观察整个表达式,例如
    watch b>20&&i>10
    ,以寻找您不希望同时为真的值组合。当您得到我喜欢它

    您可以观察变量是否变为特定值,指针是否变为NULL,范围计数器是否超过数组的最后一个元素,或者导致代码被破坏的任何其他条件。一旦它停止,您将确切知道错误发生的时间点,您可以查看其他变量以查看找出哪里出了问题

    一般来说,如果在使用调试器之前必须知道错误发生的时间和地点,那么调试器就不会那么有用了

    编辑:由于更新了您的帖子,在您的特定情况下,您只需使用
    回溯
    ,就可以直接进行迭代,例如

    paul@local:~/src/c/scratch$ gdb segfault
    GNU gdb (GDB) 7.4.1-debian
    Copyright (C) 2012 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "x86_64-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from /home/paul/src/c/scratch/segfault...done.
    (gdb) list 1,16
    1       #include <stdlib.h>
    2
    3       void segfault(int * p) {
    4           int n = *p;
    5       }
    6
    7       int main(void) {
    8           int n = 0;
    9           int * parray[] = {&n, &n, &n, &n, NULL};
    10
    11          for ( int i = 0; i < 10; ++i ) {
    12              segfault(parray[i]);
    13          }
    14
    15          return 0;
    16      }
    (gdb) run
    Starting program: /home/paul/src/c/scratch/segfault
    
    Program received signal SIGSEGV, Segmentation fault.
    0x0000000000400568 in segfault (p=0x0) at segfault.c:4
    4           int n = *p;
    (gdb) backtrace
    #0  0x0000000000400568 in segfault (p=0x0) at segfault.c:4
    #1  0x00000000004005c1 in main () at segfault.c:12
    (gdb) frame 1
    #1  0x00000000004005c1 in main () at segfault.c:12
    12              segfault(parray[i]);
    (gdb) print i
    $1 = 4
    (gdb)
    
    paul@local:~/src/c/scratch$gdb segfault
    GNU gdb(gdb)7.4.1-debian
    版权所有(C)2012免费软件基金会。
    许可证GPLv3+:GNU GPL版本3或更高版本
    这是自由软件:您可以自由更改和重新发布它。
    在法律允许的范围内,不提供任何担保。键入“显示复制”
    和“显示保修”了解详细信息。
    此GDB配置为“x86_64-linux-gnu”。
    有关错误报告说明,请参阅:
    ...
    从/home/paul/src/c/scratch/segfault读取符号…完成。
    (gdb)清单1,16
    1#包括
    2.
    3无效故障(int*p){
    4 int n=*p;
    5       }
    6.
    7内部主管道(无效){
    8 int n=0;
    9 int*parray[]={&n,&n,&n,&n,NULL};
    10
    11表示(int i=0;i<10;++i){
    12断层(帕雷[i]);
    13          }
    14
    15返回0;
    16      }
    (gdb)运行
    启动程序:/home/paul/src/c/scratch/segfault
    程序接收信号SIGSEGV,分段故障。
    SEGFULT处的SEGFULT中的0x0000000000400568(p=0x0)。c:4
    4 int n=*p;
    (gdb)回溯
    #0 0x0000000000400568处于SEGFULT(p=0x0)处于SEGFULT。c:4
    #1 0x00000000004005c1位于segfault处的main()中。c:12
    (gdb)第1帧
    #1 0x00000000004005c1位于segfault处的main()中。c:12
    12断层(帕雷[i]);
    (gdb)打印i
    $1 = 4
    (gdb)
    
    在您的情况下,您可以转到与循环所在函数对应的任何
    帧,只需执行
    print i
    即可获得循环索引。

    来源:

    您可以为任何断点(或观察点或捕捉点)提供一系列命令,以便在程序因该断点而停止时执行。例如,您可能希望打印某些表达式的值,或启用其他断点

    因此,您可以在循环中设置断点,每次命中该断点时显示迭代值
    i

    break <line number just after start of the loop> 
    commands 
    silent
    printf "i == %d\n", i
    continue
    end
    
    中断
    命令
    沉默的
    printf“i==%d\n”,i
    持续
    结束
    

    当然还有其他的(可能更有效)调试此问题的方法,但使用断点显示信息或执行其他脚本操作然后继续运行的技术是调试工具箱中的一个有价值的东西。

    我相信
    gdb
    可以打印变量值,打印交互变量…我知道这一点。问题是我不知道在哪
    paul@local:~/src/c/scratch$ gdb segfault
    GNU gdb (GDB) 7.4.1-debian
    Copyright (C) 2012 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "x86_64-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from /home/paul/src/c/scratch/segfault...done.
    (gdb) list 1,16
    1       #include <stdlib.h>
    2
    3       void segfault(int * p) {
    4           int n = *p;
    5       }
    6
    7       int main(void) {
    8           int n = 0;
    9           int * parray[] = {&n, &n, &n, &n, NULL};
    10
    11          for ( int i = 0; i < 10; ++i ) {
    12              segfault(parray[i]);
    13          }
    14
    15          return 0;
    16      }
    (gdb) run
    Starting program: /home/paul/src/c/scratch/segfault
    
    Program received signal SIGSEGV, Segmentation fault.
    0x0000000000400568 in segfault (p=0x0) at segfault.c:4
    4           int n = *p;
    (gdb) backtrace
    #0  0x0000000000400568 in segfault (p=0x0) at segfault.c:4
    #1  0x00000000004005c1 in main () at segfault.c:12
    (gdb) frame 1
    #1  0x00000000004005c1 in main () at segfault.c:12
    12              segfault(parray[i]);
    (gdb) print i
    $1 = 4
    (gdb)
    
    break <line number just after start of the loop> 
    commands 
    silent
    printf "i == %d\n", i
    continue
    end