linux之gdb(下)


一、查看运行时数据
1、 print- 查看变量值
2、 ptype - 查看类型
3、 printarray - 查看数组
4、 print* array@len - 查看动态内存
5、printx=5- 改变运行时数据


二、程序错误
1、 编译错误:编写程序的时候没有符合语言规范导致编译错误。
2、 运行时错误:编译器检查不出这种错误,但在运行的时候可能会导致程序崩溃。
3、 逻辑错误:编译和运行都很顺利,但是程序没有干它该干的事情。


三、gdb调试逻辑错误

  1. #include<stdio.h>  
  2. int main(void)  
  3. {  
  4.         inti;   
  5.         char str[6]= "hello";  
  6.         char reverse_str[6]= "";  
  7.         printf("%s\n", str);  
  8.         for (i=0; i<5; i++)  
  9.                 reverse_str[5-i]= str[i];  
  10.         printf("%s\n", reverse_str);  
  11.         return 0;  
  12. }  
#include<stdio.h>
int main(void)
{
        inti; 
        char str[6]= "hello";
        char reverse_str[6]= "";
        printf("%s\n", str);
        for (i=0; i<5; i++)
                reverse_str[5-i]= str[i];
        printf("%s\n", reverse_str);
        return 0;
}

这个程序要实现逆序输出字符串hello,但是却没有任何输出。



四、gdb调试段错误
1、 段错误是由于访问非法地址而产生的错误。
(1) 访问系统数据区,尤其是往系统保护的内存地址写数据。最常见就是给一个指针以 0 地址
(2) 内存越界 ( 数组越界,变量类型不一致等 ) 访问到不属于你的内存区域


五、core文件调试段错误
1 、 core 文件
     在程序崩溃时,一般会生成一个文件叫 core 文件。 core文件记录的是程序崩溃时的内存映像 ,并加入调试信息。core 文件生成的过程叫做 core dump

2 、设置生成 core 文件
(1) ulimit -c  查看 core-dump 状态 (ulimit -a 查看当前块大小)
(2) ulimit -c 数字 (如: ulimit -c 1024 ) (设置每一块的大小为1024)
(3) ulimit -c unlimited  (每一块的大小,没有限制)

3 、 gdb 利用 core 文件调试
(1)gdb 文件名 core文件  (若用bugging的例子, # gdb bugging core.9351
(2) bt  (查看堆栈)


六、示例
1、第一个示例
  1. //main.c  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. long func(int n);  
  5. int main(int argc, char *argv[])  
  6. {  
  7.     int i;  
  8.     int x =5;  
  9.     double z = 2.5;  
  10.     char ch = 'q';  
  11.      int arr1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};  
  12.      int *arr2 = (int *)malloc(sizeof(int) * 10);  
  13.      for (i=0; i<10; ++i)  
  14.      {  
  15.           arr2[i] = i;  
  16.      }  
  17.      printf("Entering main ...\n");  
  18.      for (i=0; i<argc; ++i)  
  19.      {  
  20.           printf("%s ", argv[i]);  
  21.      }  
  22.      printf("\n");  
  23.      long result = 0;  
  24.      for (i=1; i<=100; ++i)  
  25.      {  
  26.           result += i;  
  27.      }  
  28.      printf("result[1-100] = %ld\n", result);  
  29.      printf("result[1-10] = %ld\n", func(10));  
  30.      printf("Exiting main ...\n");  
  31.      return 0;  
  32. }  
  33. long func(int n)  
  34. {  
  35.      long sum = 0;  
  36.      int i;  
  37.      for (i=1; i<=n; ++i)  
  38.      {  
  39.           sum += i;  
  40.      }  
  41.      return sum;  
  42. }   
//main.c
#include <stdio.h>
#include <stdlib.h>
long func(int n);
int main(int argc, char *argv[])
{
    int i;
    int x =5;
    double z = 2.5;
    char ch = 'q';
     int arr1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
     int *arr2 = (int *)malloc(sizeof(int) * 10);
     for (i=0; i<10; ++i)
     {
          arr2[i] = i;
     }
     printf("Entering main ...\n");
     for (i=0; i<argc; ++i)
     {
          printf("%s ", argv[i]);
     }
     printf("\n");
     long result = 0;
     for (i=1; i<=100; ++i)
     {
          result += i;
     }
     printf("result[1-100] = %ld\n", result);
     printf("result[1-10] = %ld\n", func(10));
     printf("Exiting main ...\n");
     return 0;
}
long func(int n)
{
     long sum = 0;
     int i;
     for (i=1; i<=n; ++i)
     {
          sum += i;
     }
     return sum;
} 
#  gcc -Wall -g main.c -o main
#  gdb main
#  l
#  b 13
#  r
#  ptype x
#  ptype z
#  p arr1  (打印出数组的值)
#  p arr1[2]  (打印出数组的值)
#  p &arr1[0]  (打印出首地址)
#  p &arr1  (打印出首地址)
#  n
#  n
#  until
#  l
#  p *arr2@10  (查看arr2开始10个数组内容)
#  p *arr2@15  (查看arr2开始15个数组内容,包括未定义的)
#  p arr1@2  (查看arr1开始20个数组内容,包括未定义的;即arr1为整体,两倍长度的内容,因此为20个)
#  p *arr1@2  (查看arr1开始2个数组内容,即{0,1}
#  p *arr1[2]@2  (查看arr1[2]开始2个数组内容,即{2,3}

2、第二个示例,逻辑错误gdb调试
  1. //error.c  
  2. #include <stdio.h>  
  3. int main(void)  
  4. {  
  5.     int i;  
  6.     char str[6] = "hello";  
  7.     char reverse_str[6] = "";  
  8.     printf("%s\n", str);  
  9.     for (i=0; i<5; i++)  
  10.         reverse_str[5-i] = str[i];  
  11.     printf("%s\n", reverse_str);  
  12.     return 0;  
  13. }   
//error.c
#include <stdio.h>
int main(void)
{
    int i;
    char str[6] = "hello";
    char reverse_str[6] = "";
    printf("%s\n", str);
    for (i=0; i<5; i++)
        reverse_str[5-i] = str[i];
    printf("%s\n", reverse_str);
    return 0;
} 
#  gcc -Wall -g error.c -o error
#  gdb error
#  b 10
#  s
#  p str[i]
#  s
#  p reverse_str[5-i]
#  until
#  p i (此时i=5,即循环5次退出了)
#  p reverse_str  (打印出了"\000olleh")
解释:由于打印出第一位是“\0”,因此肯定不会打印出后续的值。
    因此我们可以做一个简单的修改,把第11句修改:reverse_str[4-i] = str[i];程序就正常输出了。

3、第三个示例,gdb调试段错误
(1) 访问系统数据区,尤其是往系统保护的内存地址写数据。最常见就是给一个指针以 0 地址
  1. //bugging.c  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. void segfault()  
  5. {  
  6.     int *p = NULL;  
  7.     *p = 100;  //向空指针赋值,产生段错误  
  8. }  
  9. int main(void)  
  10. {  
  11.     segfault();  
  12.     /* 
  13.     char buf[1] = "a"; 
  14.     buf[10003] = 'A'; 
  15.     printf("%c\n",buf[10003]); 
  16.     */  
  17.     return 0;  
  18. }   
//bugging.c
#include <stdio.h>
#include <stdlib.h>
void segfault()
{
    int *p = NULL;
    *p = 100;  //向空指针赋值,产生段错误
}
int main(void)
{
    segfault();
    /*
    char buf[1] = "a";
    buf[10003] = 'A';
    printf("%c\n",buf[10003]);
    */
    return 0;
} 
#  gcc -Wall -g bugging.c -o bugging
#  gdb bugging
#  r    (如果程序很长,直接运行,会给出段错误的位置)
#  bt  (栈回朔)
#  l 7  (打印出第7行)

(2)内存越界(数组越界,变量类型不一致等访问到不属于你的内存区域
修改bugging.c程序
  1. //bugging.c  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. void segfault()  
  5. {  
  6.     int *p = NULL;  
  7.     *p = 100;  //向空指针赋值,产生段错误  
  8. }  
  9. int main(void)  
  10. {  
  11.     //segfault();  
  12.     char buf[1] = "a";  
  13.     buf[10003] = 'A';  
  14.     printf("%c\n",buf[10003]);  
  15.     return 0;  
  16. }  
//bugging.c
#include <stdio.h>
#include <stdlib.h>
void segfault()
{
    int *p = NULL;
    *p = 100;  //向空指针赋值,产生段错误
}
int main(void)
{
    //segfault();
    char buf[1] = "a";
    buf[10003] = 'A';
    printf("%c\n",buf[10003]);
    return 0;
}
#  gcc -Wall -g bugging.c -o bugging
#  gdb bugging
#  r  (如果程序很长,直接运行,会给出段错误的位置:第14行,buf[10003] = 'A'


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值