码迷,mamicode.com
首页 > 数据库 > 详细

gdb

时间:2016-06-10 23:21:15      阅读:263      评论:0      收藏:0      [点我收藏+]

标签:gdb


1,先设置 

chunli@ubuntu:~/makefile$ ulimit -c unlimited

安装gdb

chunli@ubuntu:~/makefile$ sudo apt-get install gdb

源文件 main.c

#include <stdio.h>
int main()
{
        int *i ;
        *i = 100;
        return 0;
}


makefile文件:

.SUFFIXES:.c .o
CC=gcc
EXEC=app
SRCS=main.c
OBJS=$(SRCS:.c=.o)      #跟随SRCS的文件名前缀,相当于字符串替换
FLAGS1=-o
FLAGS2=-c

start:$(OBJS)
        $(CC)  $(FLAGS1) $(EXEC) $(OBJS)
        @echo "-------------OK---------"

.c.o:
        $(CC) -g $(FLAGS1) $@ $(FLAGS2) $<

clean:
        rm -rf $(OBJS)
        rm -rf $(EXEC)



编译:

chunli@ubuntu:~/makefile$ make
gcc -o main.o -c main.c
gcc -g -o app main.o	
-------------OK---------


运行

chunli@ubuntu:~/makefile$ ./app 
Segmentation fault (core dumped)

chunli@ubuntu:~/makefile$ ll
total 288K
-rwxrwxr-x 1 chunli chunli 8.4K Jun 10 15:05 app
-rw------- 1 chunli chunli 256K Jun 10 14:58 core
-rw-rw-r-- 1 chunli chunli   67 Jun 10 14:56 main.c
-rw-rw-r-- 1 chunli chunli 1.3K Jun 10 15:05 main.o
-rw-rw-r-- 1 chunli chunli  305 Jun 10 14:59 makefile
chunli@ubuntu:~/makefile$



运行gdb

chunli@ubuntu:~/makefile$ gdb app core


查看哪儿出错了

(gdb) where
#0  0x00000000004004f5 in main ()


==========================================================

项目源文件:

这是一个可以正常编译,但执行就出错的程序:

修改了delete函数部分信息,调用时删除一个不存在的节点

chunli@ubuntu:~/gdb$ cat main.c 
//单向链表
#include <stdio.h>
#include <stdlib.h>
 
struct list //链表结构体
{
	int data;		// 数据
	struct list *next;	//指针域,指向一下个域的指针
};

struct list *create_list()//创建一个节点,返回值为list结构体指针
{
	return calloc(sizeof(struct list),1);
}

void traverse(struct list *ls)			//遍历链表
{
	if(ls)		//只要地址不为NULL
	{
		//先序递归
		printf("地址 %p,本节点的值 %d \n",ls,ls->data);
		traverse(ls->next);
		
	}
}

struct list *insert_list(struct list *ls,int n,int data)	//在指定位置插入元素,(首节点,在第几个节点插入,这个节点的data值)
{	
	struct list *p = ls;
	while(p && n--)
	{
		p = p->next;
	}
	if(!p) return NULL;//n指向了一个无效的位置
	else
	{
		struct list *node = create_list();
		node->data = data;
		//掐断原来的链表,重新组合
		node->next = p->next;
		p->next    = node;
		return node;
	}
}
int delete_list(struct list *ls,int n)		//删除链表元素,1链表首元素,要删除第几个?
{
	struct list *p = ls;
	while(p && n--)
	{
		p = p->next;
	}
	//if(!p) return 0;//n指向了一个无效的位置
	//else
	{
		struct list *node = p->next;	//记录待删除节点的地址
		//if(!node) return 0;		//如果这个节点是无效的,就返回无效
		p->next = node->next;		//将该节点next指向待删除节点的next节点的next节点
		free(node);
		return 1;			//操作成功!
	}
	
}

int count_list(struct list *ls)		//返回链表元素个数,包括首节点
{
	struct list *p = ls->next;
	int count = 0;
	while(p)
	{
		count++;
		p = p->next;
	}
	return count;
}

void  clear_list(struct list *ls)	//清空链表,保留首节点
{
	struct list *p   = ls->next;	//要跳过首节点,进入该链表的第一个有效元素
	struct list *tmp;
	while(p)
	{	
		tmp = p->next;		//记录当前节点的next
		free(p);		//释放这个有效的元素
		p = tmp;
	}
	ls->next = NULL;		//链表清空后,首节点就是尾节点,一定设置为NULL
}

int empty_list(struct list *ls)	//返回链表是否为空
{
	if(ls->next)		//如果不为空,返回1
		return 1;	
	else			//如果  为空,返回0
		return 0;
}
struct list *local_list(struct list *ls,int n)		//返回链表对应的第N个节点的地址
{
	struct list *p = ls->next;			//立即指向首节点的下一个元素
	while(p && n--)
	{
		p = p->next;
	}
	return p;
}

struct list *elem_local(struct list *ls,int data)	//返回链表中数据域值data的节点地址
{
	struct list *p = ls->next;			//立即指向首节点的下一个元素
	while(p)
	{
		if(p ->data == data) {break;}
		p = p->next;
	}
	return p;
}
	
int elem_pos(struct list *ls,int data)		//返回链表中数据域值data的节点的序号
{
	struct list *p = ls->next;			//立即指向首节点的下一个元素
	int count = 0;
	while(p)
	{
		if(p ->data == data) {break;}
		p = p->next;
		count++;
	}
	return count;
}

struct list *last_list(struct list *ls)		//返回链表的最后一个元素
{
	struct list *p  =ls->next;
	struct list *back = p;			
	while(p)
	{
		back = p;
		p = p->next;
	}
	return back;
}
void merge_list(struct list *ls1,struct list *ls2)	//把链表2的有效元素合并到链表1
{
	struct list *last = last_list(ls1);
	last->next = ls2->next;
}
void reverse_list(struct list *ls)			//逆置链表
{
	if(!(ls || ls->next || ls->next->next)) {return ;}	//只有大于1个有效节点,才需要逆置
	struct list *left   = NULL;				//记录上一个节点的地址,初始值的NULL刚好可以作为尾节点的next的NULL
	struct list *curr   = ls->next;				//记录当前节点的地址
	struct list *right  = NULL;				//遍历完原链表的所以元素
	while(curr)						//遍历完原链表的所有元素
	{
		right      = curr->next;			//下一个节点就是当前节点的next
		curr->next = left;				//第一次执行的时候,curr节点就是尾节点了,就将尾节点的next指向了NULL
		left       = curr;				//把当前的节点作为上一个节点
		curr       = right;				//把下一个节点作为当前节点
	}
	ls->next = left;					//原链表的最后的一个有效元素就已经变为left了,让链表节点指向这个left就好了。
}


int main()
{


	/*	链表ADT操作的代码实现		*/
	printf("\n\n\n开始批量创建链表\n");
	struct list *node_start = create_list();	//此时链表的长度只有1个,有效元素个数为0
	for(int i=0;i<4;i++)				//在原来的首节点上插入10个,结果就是11个
	{
		//链表插入只能在首节点之后
		//insert_list(node_start,i,i+100);	//每次都在第i个位置插入,越后来插入的越靠后
		insert_list(node_start,0,i+100);	//每次都在第0个位置插入,越后来插入的越靠前
	}

	delete_list(node_start,30);			//在指定位置删除节点
	insert_list(node_start,2,666);			//在指定位置插入节点
	traverse(node_start);				//遍历链表
	printf("链表有效元素有%d个(不包括首节点)\n",count_list(node_start));	//返回这个链表元素的个数
	printf("第2个节点的数据是%d\n",local_list(node_start,2)->data);		//返回链表第N个有效元素的地址
	printf("最后一个元素的数据域是 %d\n",last_list(node_start)->data);	//返回链表 最后一个元素的地址

	printf("\n\n链表合并,结果输出\n");
	struct list *node2 = create_list();	
	for(int i=0;i<8;i++)				
	{
		insert_list(node2,0,i+33);	
	}
	merge_list(node_start,node2);			//把node2合并到node_start
	traverse(node_start);				//遍历链表

	printf("\n逆置链表,结果输出\n");
	reverse_list(node_start);
	traverse(node_start);				//遍历链表

	printf("\n\n\n清空链表\n");
	clear_list(node_start);				//清空链表
	traverse(node_start);				//遍历链表


	

	return 0;
}



提供makefile文件

chunli@ubuntu:~/gdb$ cat makefile 
.SUFFIXES:.c .o
CC=gcc -std=c99
EXEC=app
SRCS=main.c

OBJS=$(SRCS:.c=.o)	#跟随SRCS的文件名前缀,相当于字符串替换
FLAGS1=-o
FLAGS2=-c

start:$(OBJS)
	$(CC)  $(FLAGS1) $(EXEC) $(OBJS)
	@echo "-------------OK---------"

.c.o:
	$(CC) -g $(FLAGS1) $@ $(FLAGS2) $<

clean:
	rm -rf $(OBJS)
	rm -rf $(EXEC)
chunli@ubuntu:~/gdb$


1【利用内核的信息查看错误】

[打开core]
chunli@ubuntu:~/gdb$ ulimit -c unlimited

[编译]
chunli@ubuntu:~/gdb$ make 
gcc -std=c99 -g -o main.o -c main.c
gcc -std=c99  -o app main.o	
-------------OK---------

[运行]
chunli@ubuntu:~/gdb$ ./app 
Segmentation fault (core dumped)


[开始调试]
chunli@ubuntu:~/gdb$ gdb app core

[输入where,告诉你哪儿错了,在主程序的177行,在delete_list函数,55行]
(gdb) where
#0  0x0000000000400723 in delete_list (ls=0x1305010, n=25) at main.c:55
#1  0x0000000000400a16 in main () at main.c:177


		


【gdb查错】

chunli@ubuntu:~/gdb$ gdb app

[键入run]
(gdb) run
Starting program: /home/chunli/gdb/app 
开始批量创建链表
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400723 in delete_list (ls=0x603010, n=25) at main.c:55
55			struct list *node = p->next;	//记录待删除节点的地址

[键入where]
(gdb) where
#0  0x0000000000400723 in delete_list (ls=0x603010, n=25) at main.c:55
#1  0x0000000000400a16 in main () at main.c:177
(gdb) 

[可以很清晰的看到在主程序的第55行,出了问题]


[列出出错的上下文]
(gdb) list
50			p = p->next;
51		}
52		//if(!p) return 0;//n指向了一个无效的位置
53		//else
54		{
55			struct list *node = p->next;	//记录待删除节点的地址
56			//if(!node) return 0;		//如果这个节点是无效的,就返回无效
57			p->next = node->next;		//将该节点next指向待删除节点的next节点的next节点
58			free(node);
59			return 1;			//操作成功!


【设置断点】

[运行gdb]
chunli@ubuntu:~/gdb$ gdb app

[设置断点]从上面可以看出55行出错
(gdb) break 55

[让程序跑]
(gdb) run

[停下来了,看看此时p的是多少]
(gdb) print p
$1 = (struct list *) 0x0

[查看变量类型]
(gdb) whatis p
type = struct list *

[在指定文件的行数加入断点]
(gdb) break main.c:100

[info 提供信息]
当前在第一个断点,还有一个断点
(gdb) info break
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040071f in delete_list at main.c:55
	breakpoint already hit 1 time
2       breakpoint     keep y   0x0000000000400812 in local_list at main.c:100




【把上面原程序中的delete_list换成下面的】

int delete_list(struct list *ls,int n)          //删除链表元素,1链表首元素,要删除第几个?
{
        struct list *p = ls;
        while(p && n--)
        {
                p = p->next;
        }
        if(!p) return 0;//n指向了一个无效的位置
        else
        {
                struct list *node = p->next;    //记录待删除节点的地址
                if(!node) return 0;             //如果这个节点是无效的,就返回无效
                p->next = node->next;           //将该节点next指向待删除节点的next节点的next节点
                free(node);
                return 1;                       //操作成功!
        }

}

主函数的delete也换换
    delete_list(node_start,0);


重新编译:

delete的调用显示在主函数的200行
[运行gdb]
chunli@ubuntu:~/gdb$ gdb app 
(gdb) break main.c:200		【在主函数的第200行设置断点】
(gdb) run					
(gdb) list					【列出上下文】
(gdb) set variable node_start=0x0000【修改一个变量的值】
(gdb) step					【当遇到函数,step就是进入函数】
delete_list (ls=0x0, n=0) at main.c:47
47		struct list *p = ls;
(gdb) step					【进入函数内部】
48		while(p && n--)
(gdb) next					【下一步,不会进入函数内部】
202		traverse(node_start);				//遍历链表



【gdb return 的使用】

chunli@ubuntu:~/gdb$ gdb app 
(gdb) break main.c:169
(gdb) run
(gdb) return 0
Make main return now? (y or n) y


本文出自 “魂斗罗” 博客,请务必保留此出处http://990487026.blog.51cto.com/10133282/1787808

gdb

标签:gdb

原文地址:http://990487026.blog.51cto.com/10133282/1787808

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!