Gdb 无法插入断点0

Gdb 无法插入断点0,gdb,Gdb,出于某种原因,GDB在步进我开发的守护进程时停止运行,我找不到哪里出了问题。在对代码进行了一些更改后,问题开始出现,出现了分段错误。为了跟踪错误,我通过gdb运行了守护进程,就像我在这种情况下经常做的那样,但是这次,我的错误代码似乎正在破坏gdb本身。在这种情况下会出现什么问题以及如何处理?我附加了已更改函数的执行跟踪。在826行,我动态调用一个函数,也许这与此有关?蒂亚 Breakpoint 1, serve_outlinks_stage1 (conn_id=31, job_idx=241)

出于某种原因,GDB在步进我开发的守护进程时停止运行,我找不到哪里出了问题。在对代码进行了一些更改后,问题开始出现,出现了分段错误。为了跟踪错误,我通过gdb运行了守护进程,就像我在这种情况下经常做的那样,但是这次,我的错误代码似乎正在破坏gdb本身。在这种情况下会出现什么问题以及如何处理?我附加了已更改函数的执行跟踪。在826行,我动态调用一个函数,也许这与此有关?蒂亚

Breakpoint 1, serve_outlinks_stage1 (conn_id=31, job_idx=241) at dependency.c:320
320     job_data=jobs[job_idx].data;
(gdb) step
322     fl_iocbs_top--;
(gdb) 
323     if (fl_iocbs_top==0) {
(gdb) 
327     iocb_idx=fl_iocbs[fl_iocbs_top];
(gdb) 
328     memset(&iocbs[iocb_idx],0,sizeof(struct iocb));
(gdb) 
329     iocb_ptrs[num_iocb_submits]=&iocbs[iocb_idx];
(gdb) 
330     num_iocb_submits++;
(gdb) 
331     io_prep_pread(&iocbs[iocb_idx],company_infos[cliconns[conn_id].company_idx].fd_dependencies,&jobs[job_idx].aux.outlinks_id,sizeof(uint),sizeof(t_dependency_t)*job_data->dep_id+offsetof(t_dependency_t,tail_outlinks_id));
(gdb) 
io_prep_pread (iocb=0x620020 <iocbs+1216>, fd=20, buf=0x68f300 <jobs+13536>, count=4, offset=274) at /usr/include/libaio.h:173
173     memset(iocb, 0, sizeof(*iocb));
(gdb) 
174     iocb->aio_fildes = fd;
(gdb) 
175     iocb->aio_lio_opcode = IO_CMD_PREAD;
(gdb) 
176     iocb->aio_reqprio = 0;
(gdb) 
177     iocb->u.c.buf = buf;
(gdb) 
178     iocb->u.c.nbytes = count;
(gdb) 
179     iocb->u.c.offset = offset;
(gdb) 
180 }
(gdb) 
serve_outlinks_stage1 (conn_id=31, job_idx=241) at dependency.c:332
332     callback=iocb_idx;
(gdb) 
333     io_set_callback(&iocbs[iocb_idx], (io_callback_t) callback);
(gdb) 
io_set_callback (iocb=0x620020 <iocbs+1216>, cb=0x13) at /usr/include/libaio.h:168
168     iocb->data = (void *)cb;
(gdb) 
169 }
(gdb) 
serve_outlinks_stage1 (conn_id=31, job_idx=241) at dependency.c:334
334     aio_infos[iocb_idx].job_idx=job_idx;
(gdb) 
335     aio_infos[iocb_idx].conn_id=conn_id;
(gdb) 
336     aio_infos[iocb_idx].op_code=AIO_OP_READ_DEPENDENCY_OUTLINKS_ID;
(gdb) 
337     jobs[job_idx].pending_ops++;
(gdb) 
338 }
(gdb) 
process_command (conn_id=31, job_idx=241) at depserv.c:493
493             break;
(gdb) 
565 }
(gdb) 
main_event_loop () at depserv.c:1087
1087                                    _assign_job(job_idx);   
(gdb) 
jobs_top=240, job_idx[jobs_top]=240
1088                                    memset(&jobs[job_idx],0,sizeof(jobs[job_idx]));
(gdb) 
1089                                    jobs[job_idx].conn_id=conn_id;
(gdb) 
1090                                    jobs[job_idx].company_idx=cliconns[conn_id].company_idx;
(gdb) 
1075                    while(count>0) {
(gdb) 
1078                        count = read (infd, &jobs[job_idx].dscmd, sizeof(dscmd_t));
(gdb) 
1079                        printf("count=%zd\n",count);
(gdb) 
count=-1
1080                        if (count>0) {
(gdb) 
1098                            if (count==0) {
(gdb) 
1101                                break;
(gdb) 
1049            for (i = 0; i < n; i++) {
(gdb) 
1108        } // while
(gdb) 
982         usleep(2000);   // for debugging because we need pending_aio_submits to be valid, should be removed for production
(gdb) 
983         check_aio();
(gdb) 
check_aio () at depserv.c:807
807     num_events = io_getevents(io_ctx, 0, MAX_IO_EVENTS, aio_events, NULL);
(gdb) 
808     if (num_events<0) {
(gdb) 
811         for(i=0;i<num_events;i++) {
(gdb) 
843     if (num_iocb_submits>0) {
(gdb) 
845         write_cycle();
(gdb) 
write_cycle () at depserv.c:225
225     for(i=0,j=0;i<num_iocb_submits;i++) {
(gdb) 
226         callback=(long) iocb_ptrs[i]->data;
(gdb) 
227         iocb_idx=callback;
(gdb) 
228         switch(aio_infos[iocb_idx].op_code) {
(gdb) 
225     for(i=0,j=0;i<num_iocb_submits;i++) {
(gdb) 
245     if (!j) return;
(gdb) 
269 }
(gdb) 
check_aio () at depserv.c:846
846         for(i=0;i<num_iocb_submits;i++) {
(gdb) 
847             ret = io_submit(io_ctx, 1, &iocb_ptrs[i]);
(gdb) 
848             if (ret<0) printf("bad iosubmit ret=%d\n",ret);
(gdb) 
846         for(i=0;i<num_iocb_submits;i++) {
(gdb) 
850         pending_aio_submits=pending_aio_submits+1;
(gdb) 
856         num_iocb_submits=0;
(gdb) 
858 }
(gdb) 
main_event_loop () at depserv.c:985
985         n=MAX_IOCBS-fl_iocbs_top;
(gdb) 
986         if (pending_aio_submits>n) {
(gdb) 
990         if (recvfrom(identityd_socket, udp_buf, MAX_UDP_PACKET_SIZE, 0,  (struct sockaddr*) &remote_addr, &slen)==-1) {
(gdb) 
995         if (!announced) continue;
(gdb) 
997         n = epoll_wait(listening_efd, listening_events, MAX_EPOLL_EVENTS_LISTEN, 1);
(gdb) 
1000            for (i = 0; i < n; i++) {
(gdb) 
1048            n = epoll_wait(accepted_efd, accepted_events, MAX_EPOLL_EVENTS_ACCEPTED, 1);
(gdb) 
1049            for (i = 0; i < n; i++) {
(gdb) 
1108        } // while
(gdb) 
982         usleep(2000);   // for debugging because we need pending_aio_submits to be valid, should be removed for production
(gdb) 
983         check_aio();
(gdb) 
check_aio () at depserv.c:807
807     num_events = io_getevents(io_ctx, 0, MAX_IO_EVENTS, aio_events, NULL);
(gdb) 
808     if (num_events<0) {
(gdb) 
811         for(i=0;i<num_events;i++) {
(gdb) 
812             pending_aio_submits--;
(gdb) 
813             iocb_ptr=aio_events[i].obj;
(gdb) 
814             callback=(long) iocb_ptr->data;
(gdb) 
815             iocb_idx=callback;
(gdb) 
816             op_code=aio_infos[iocb_idx].op_code;
(gdb) 
817             job_idx=aio_infos[iocb_idx].job_idx;
(gdb) 
818             if (job_idx!=MAX_JOBS) {
(gdb) 
819                 jobs[job_idx].pending_ops--;
(gdb) 
821             func=aio_op_funcs[op_code];
(gdb) 
822             if (func==0) {
(gdb) 
826             func(iocb_ptr,aio_events[i].res);
(gdb) 
serve_outlinks_stage2 (iocb_ptr=0x620020 <iocbs+1216>, res=4) at dependency.c:346
346     if (res!=iocb_ptr->u.c.nbytes) {    /// error
(gdb) 
350     callback=(long) iocb_ptr->data;
(gdb) 
351     iocb_idx=callback;
(gdb) 
352     job_idx=aio_infos[iocb_idx].job_idx;
(gdb) 
353     conn_id=aio_infos[iocb_idx].conn_id;
(gdb) 
355     outlinks_id=jobs[job_idx].aux.outlinks_id;  
(gdb) 
356     job_data=(job_read_outlinks_t*) malloc(sizeof(job_read_outlinks_t));    
(gdb) 
357     if (!job_data) {
(gdb) 
361     memset(&job_data,0,sizeof(job_read_outlinks_t));
(gdb) print outlinks_id
$1 = 2
(gdb) step
362     jobs[job_idx].data=job_data;
(gdb) 
364     fl_iocbs_top--;
(gdb) 
365     if (fl_iocbs_top==0) {
(gdb) 
369     iocb_idx=fl_iocbs[fl_iocbs_top];    
(gdb) 
370     memset(&iocbs[iocb_idx],0,sizeof(struct iocb));
(gdb) 
371     iocb_ptrs[num_iocb_submits]=&iocbs[iocb_idx];
(gdb) 
372     num_iocb_submits++;
(gdb) 
373     io_prep_pread(&iocbs[iocb_idx],company_infos[cliconns[conn_id].company_idx].fd_outlinks,&job_data->r_outlinks,sizeof(t_outlinks_t),sizeof(t_outlinks_t)*outlinks_id);
(gdb) 
io_prep_pread (iocb=0x61ffe0 <iocbs+1152>, fd=0, buf=0x10, count=32, offset=0) at /usr/include/libaio.h:173
173     memset(iocb, 0, sizeof(*iocb));
(gdb) 
174     iocb->aio_fildes = fd;
(gdb) 
175     iocb->aio_lio_opcode = IO_CMD_PREAD;
(gdb) 
176     iocb->aio_reqprio = 0;
(gdb) 
177     iocb->u.c.buf = buf;
(gdb) 
178     iocb->u.c.nbytes = count;
(gdb) 
179     iocb->u.c.offset = offset;
(gdb) 
180 }
(gdb) 
serve_outlinks_stage2 (iocb_ptr=0x620020 <iocbs+1216>, res=4) at dependency.c:374
374     callback=iocb_idx;
(gdb) 
375     io_set_callback(&iocbs[iocb_idx], (io_callback_t) callback);
(gdb) 
io_set_callback (iocb=0x61ffe0 <iocbs+1152>, cb=0x12) at /usr/include/libaio.h:168
168     iocb->data = (void *)cb;
(gdb) 
169 }
(gdb) 
serve_outlinks_stage2 (iocb_ptr=0x620020 <iocbs+1216>, res=4) at dependency.c:376
376     aio_infos[iocb_idx].job_idx=job_idx;
(gdb) 
377     aio_infos[iocb_idx].conn_id=conn_id;
(gdb) 
378     aio_infos[iocb_idx].op_code=AIO_OP_READ_OUTLINKS;
(gdb) 
379     jobs[job_idx].pending_ops++;
(gdb) 
380     return(0);
(gdb) 
381 }
(gdb) 
Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x0

0x0000000000000000 in ?? ()
(gdb) 
Cannot find bounds of current function
(gdb) 
断点1,在dependency.c:320处服务链接1级(conn\u id=31,job\u idx=241)
320作业数据=作业[job\u idx]。数据;
(gdb)步骤
322 fl_iocbs_top--;
(gdb)
323如果(fl\U iocbs\U top==0){
(gdb)
327 iocb_idx=fl_iocbs[fl_iocbs_top];
(gdb)
328个memset(&iocbs[iocb_idx],0,sizeof(struct iocb));
(gdb)
329 iocb_ptrs[num_iocb_submits]=&iocbs[iocb_idx];
(gdb)
330个iocb提交++;
(gdb)
331 io_prep_pread(&iocbs[iocb_idx],company_infos[cliconns[conn_id].company_idx].fd_dependencies,&jobs[job_idx].aux.outlinks_id,sizeof(uint),sizeof(t_dependencity_t)*job_data->dep_id+offset(t_dependencity_,tail_outlinks_id));
(gdb)
在/usr/include/libaio.h:173处的io准备(iocb=0x620020,fd=20,buf=0x68f300,计数=4,偏移量=274)
173个成员集(iocb,0,sizeof(*iocb));
(gdb)
174 iocb->aio_fildes=fd;
(gdb)
175 iocb->aio\U lio\U操作码=IO\U CMD\U前置;
(gdb)
176 iocb->aio_reqprio=0;
(gdb)
177 iocb->u.c.buf=buf;
(gdb)
178 iocb->u.c.N字节=计数;
(gdb)
179 iocb->u.c.偏移=偏移;
(gdb)
180 }
(gdb)
在dependency.c:332处,为第1阶段(连接id=31,作业id=241)服务
332回调=iocb_idx;
(gdb)
333 io_集合_回调(&iocbs[iocb_idx],(io_回调_t)回调);
(gdb)
io设置回调(iocb=0x620020,cb=0x13)位于/usr/include/libaio.h:168
168 iocb->data=(void*)cb;
(gdb)
169 }
(gdb)
在dependency.c:334中,为第1阶段(连接id=31,作业id=241)提供大纲链接
334 aio_infos[iocb_idx].job_idx=job_idx;
(gdb)
335 aio_infos[iocb_idx].conn_id=conn_id;
(gdb)
336 aio_infos[iocb_idx].op_code=aio_op_READ_DEPENDENCY_OUTLINKS_ID;
(gdb)
337个作业[job_idx]。挂起的作业++;
(gdb)
338 }
(gdb)
在depserv.c:493处处理命令(conn_id=31,job_idx=241)
493次中断;
(gdb)
565 }
(gdb)
depserv.c:1087上的主事件循环()
1087分配作业(作业idx);
(gdb)
jobs\u top=240,job\u idx[jobs\u top]=240
1088内存集(&jobs[job_idx],0,sizeof(jobs[job_idx]);
(gdb)
1089个作业[job_idx].conn_id=conn_id;
(gdb)
1090个作业[job_idx]。公司idx=cliconns[conn_id]。公司idx;
(gdb)
1075时(计数>0){
(gdb)
1078 count=read(infd,&jobs[job_idx].dscmd,sizeof(dscmd_t));
(gdb)
1079 printf(“计数=%zd\n”,计数);
(gdb)
计数=-1
1080如果(计数>0){
(gdb)
1098如果(计数=0){
(gdb)
1101次中断;
(gdb)
1049表示(i=0;iaio_reqprio=0;
(gdb)
177 iocb->u.c.buf=buf;
(gdb)
178 iocb->u.c.N字节=计数;
(gdb)
179 iocb->u.c.偏移=偏移;
(gdb)
180 }
(gdb)
在dependency.c:374处提供阶段2(iocb\U ptr=0x6200,res=4)的大纲链接
374 callback=iocb_idx;
(gdb)
375 io_集合_回调(&iocbs[iocb_idx],(io_回调_t)回调);
(gdb)
io_set_回调(iocb=0x61ffe0,cb=0x12)位于/usr/include/libaio.h:168
168 iocb->data=(void*)cb;
(gdb)
169 }
(gdb)
在dependency.c:376处提供阶段2(iocb\U ptr=0x6200,res=4)的大纲链接
376 aio_infos[iocb_idx].job_idx=job_idx;
(gdb)
377 aio_infos[iocb_idx].conn_id=conn_id;
(gdb)
378 aio_infos[iocb_idx].op_code=aio_op_READ_OUTLINKS;
(gdb)
379个作业[job_idx]。挂起的作业++;
(gdb)
380返回(0);
(gdb)
381 }
(gdb)
警告:
无法插入断点0。
无法访问地址0x0处的内存
0x0000000000000000英寸???()
(gdb)
找不到当前函数的边界
(gdb)
我的坏代码似乎正在破坏GDB本身

不,没有。这是:

381 }
(gdb) 
Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x0

0x0000000000000000 in ?? ()
(gdb) 
Cannot find bounds of current function
通常意味着您的程序已跳转到位置0,并且GDB无法为
步骤
命令设置内部断点

这种“返回到0”的最可能原因是堆栈损坏:您用0重写了返回地址

您可以使用
run
来验证这一点,而不是单步执行程序。如果
run
也会像这样终止:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
那么我的猜测就被证实了。那么你能做些什么来捕捉这个错误呢

让我们举一个例子:

#include <string.h>

int foo()
{
  char buf[1];
  memset(buf, 0, 1024);
}

int main()
{
  return foo();
}
接下来,我们确认(返回)堆栈仍然完好无损:

(gdb) bt
#0  foo () at t.c:6
#1  0x000000000040055b in main () at t.c:11
现在我们需要在堆栈上找到存储返回地址的位置:

(gdb) disas
Dump of assembler code for function foo:
   0x000000000040052d <+0>: push   %rbp
   0x000000000040052e <+1>: mov    %rsp,%rbp
   0x0000000000400531 <+4>: sub    $0x10,%rsp
=> 0x0000000000400535 <+8>: lea    -0x1(%rbp),%rax
   0x0000000000400539 <+12>:    mov    $0x400,%edx
   0x000000000040053e <+17>:    mov    $0x0,%esi
   0x0000000000400543 <+22>:    mov    %rax,%rdi
   0x0000000000400546 <+25>:    callq  0x400410 <memset@plt>
   0x000000000040054b <+30>:    leaveq
   0x000000000040054c <+31>:    retq
End of assembler dump.
最后,我们在位置
0x7fffffffe2b8
上设置了一个观察点,因此当该位置被覆盖时,GDB将停止:

(gdb) watch *(int**)0x7fffffffe2b8
Hardware watchpoint 2: *(int**)0x7fffffffe2b8
最后,我们继续:

(gdb) c
Continuing.
Hardware watchpoint 2: *(int**)0x7fffffffe2b8

Old value = (int *) 0x40055b <main+14>
New value = (int *) 0x0
memset () at ../sysdeps/x86_64/memset.S:79
79  ../sysdeps/x86_64/memset.S: No such file or directory.
最后,让我们看看通过此程序执行的
步骤
ping是否会产生与原始程序相同的结果

(gdb) r
Starting program: /tmp/a.out

Breakpoint 1, foo () at t.c:6
6     memset(buf, 0, 1024);
(gdb) n
7   }
(gdb) s
Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x0

0x0000000000000000 in ?? ()

是的,它是.QED。

我发现了问题:job\u data=(job\u read\u outlinks\u t*)malloc(sizeof(job\u read\u outlinks\t));此变量不应在该函数中更改,因为它是在外部分配的。但无论如何,此gdb错误非常奇怪,我一直认为我可以依靠gdb删除代码中的任何错误,但现在我认为我的调试能力消失了。可能是我可以
(gdb) c
Continuing.
Hardware watchpoint 2: *(int**)0x7fffffffe2b8

Old value = (int *) 0x40055b <main+14>
New value = (int *) 0x0
memset () at ../sysdeps/x86_64/memset.S:79
79  ../sysdeps/x86_64/memset.S: No such file or directory.
(gdb) bt
#0  memset () at ../sysdeps/x86_64/memset.S:79
#1  0x000000000040054b in foo () at t.c:6
#2  0x0000000000000000 in ?? ()
(gdb) r
Starting program: /tmp/a.out

Breakpoint 1, foo () at t.c:6
6     memset(buf, 0, 1024);
(gdb) n
7   }
(gdb) s
Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x0

0x0000000000000000 in ?? ()