欢迎大家阅读参考,如有错误或疑问请留言纠正,谢谢
一、查看运行时数据
1、
print-
查看变量值
2、
ptype
-
查看类型
3、
printarray -
查看数组
4、
print*
array@len
-
查看动态内存
5、printx=5- 改变运行时数据
二、程序错误
1、
编译错误:编写程序的时候没有符合语言规范导致编译错误。
2、
运行时错误:编译器检查不出这种错误,但在运行的时候可能会导致程序崩溃。
3、
逻辑错误:编译和运行都很顺利,但是程序没有干它该干的事情。
三、gdb调试逻辑错误
#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、第一个示例
//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调试
//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
地址
//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程序
//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')