visual studio saltar puntos punto puede propiedades pero paso operadores interrupción interrupcion hacer establecidos enlazados ejecutar debug cargar aun actualmente activará c++ debugging gdb

c++ - puntos - visual studio saltar propiedades y operadores



¿Cómo establecer un punto de interrupción en GDB donde se devuelve la función? (7)

Contrariamente a las respuestas hasta ahora, la mayoría de los compiladores crearán una única instrucción de conjunto de retorno, independientemente de cuántas declaraciones de return en la función (es conveniente que el compilador haga eso, de modo que solo haya un lugar para realizar todo el marco de pila). limpiar).

Si desea detenerse en esa instrucción, todo lo que tiene que hacer es disas y buscar retq (o cualquiera que sea la instrucción de retorno para su procesador), y establecer un punto de interrupción en ella. Por ejemplo:

int foo(int x) { switch(x) { case 1: return 2; case 2: return 3; default: return 42; } } int main() { return foo(0); } (gdb) disas foo Dump of assembler code for function foo: 0x0000000000400448 <+0>: push %rbp 0x0000000000400449 <+1>: mov %rsp,%rbp 0x000000000040044c <+4>: mov %edi,-0x4(%rbp) 0x000000000040044f <+7>: mov -0x4(%rbp),%eax 0x0000000000400452 <+10>: mov %eax,-0xc(%rbp) 0x0000000000400455 <+13>: cmpl $0x1,-0xc(%rbp) 0x0000000000400459 <+17>: je 0x400463 <foo+27> 0x000000000040045b <+19>: cmpl $0x2,-0xc(%rbp) 0x000000000040045f <+23>: je 0x40046c <foo+36> 0x0000000000400461 <+25>: jmp 0x400475 <foo+45> 0x0000000000400463 <+27>: movl $0x2,-0x8(%rbp) 0x000000000040046a <+34>: jmp 0x40047c <foo+52> 0x000000000040046c <+36>: movl $0x3,-0x8(%rbp) 0x0000000000400473 <+43>: jmp 0x40047c <foo+52> 0x0000000000400475 <+45>: movl $0x2a,-0x8(%rbp) 0x000000000040047c <+52>: mov -0x8(%rbp),%eax 0x000000000040047f <+55>: leaveq 0x0000000000400480 <+56>: retq End of assembler dump. (gdb) b *0x0000000000400480 Breakpoint 1 at 0x400480 (gdb) r Breakpoint 1, 0x0000000000400480 in foo () (gdb) p $rax $1 = 42

Tengo una función de C ++ que tiene muchas declaraciones de devolución en varios lugares. ¿Cómo establecer un punto de interrupción en la declaración de retorno donde la función realmente devuelve?

¿Y qué significa "romper" el comando sin argumento?


La ruptura sin argumento establece un punto de interrupción en la línea actual.

No hay forma de que un solo punto de interrupción capture todas las rutas de retorno. Establezca un punto de interrupción en la persona que llama inmediatamente después de que regrese, o rompa en todas las declaraciones de return .

Dado que esto es C ++, supongo que podrías crear un objeto de centinela local y romper su destructor, sin embargo.


Puede utilizar la depuración inversa para averiguar dónde devuelve realmente la función. Termine de ejecutar el fotograma actual, realice el paso inverso y luego debe detenerse en la declaración que acaba de devolver.

(gdb) record (gdb) fin (gdb) reverse-step


Si puede cambiar el código fuente, puede usar algún truco sucio con el preprocesador:

void on_return() { } #define return return on_return(), /* If the function has a return value != void */ #define return return on_return() /* If the function has a return value == void */ /* <<<-- Insert your function here -->>> */ #undef return

A continuación, establezca un punto de interrupción en on_return y on_return un fotograma.

Atención: esto no funcionará si una función no regresa a través de una declaración de return . Así que asegúrate de que la última línea sea una return .

Ejemplo (copiado descaradamente del código C, pero también funcionará en C ++):

#include <stdio.h> /* Dummy function to place the breakpoint */ void on_return(void) { } #define return return on_return() void myfun1(int a) { if (a > 10) return; printf("<10/n"); return; } #undef return #define return return on_return(), int myfun2(int a) { if (a < 0) return -1; if (a > 0) return 1; return 0; } #undef return int main(void) { myfun1(1); myfun2(2); }

La primera macro cambiará

return;

a

return on_return();

Lo cual es válido, ya que on_return también devuelve void .

La segunda macro cambiará

return -1;

a

return on_return(), -1;

Lo que llamará a on_return() y luego devolverá -1 (gracias a , -operator).

Este es un truco muy sucio, pero a pesar de usar pasos hacia atrás, también funcionará en entornos de subprocesos múltiples y funciones integradas.


rr depuración inversa

Similar al record GDB mencionado en https://.com/a/3649698/895245 , pero mucho más funcional a partir de GDB 7.11 vs rr 4.1.0 en Ubuntu 16.04.

En particular, se trata de AVX correctamente:

lo que le impide trabajar con las llamadas de biblioteca estándar por defecto.

Instalar Ubuntu 16.04.

sudo apt-get install rr linux-tools-common linux-tools-generic linux-cloud-tools-generic sudo cpupower frequency-set -g performance

Pero también considera compilar desde la fuente para obtener las últimas actualizaciones, no fue difícil.

Programa de prueba:

int where_return(int i) { if (i) return 1; else return 0; } int main(void) { where_return(0); where_return(1); }

compilar y ejecutar:

gcc -O0 -ggdb3 -o reverse.out -std=c89 -Wextra reverse.c rr record ./reverse.out rr replay

Ahora queda dentro de una sesión de GDB, y puede revertir adecuadamente la depuración:

(rr) break main Breakpoint 1 at 0x56057c458619: file a.c, line 9. (rr) continue Continuing. Breakpoint 1, main () at a.c:9 9 where_return(0); (rr) step where_return (i=0) at a.c:2 2 if (i) (rr) finish Run till exit from #0 where_return (i=0) at a.c:2 main () at a.c:10 10 where_return(1); Value returned is $1 = 0 (rr) reverse-step where_return (i=0) at a.c:6 6 } (rr) reverse-step 5 return 0;

Ahora estamos en la línea de retorno correcta.


Romper en todos los retq de la función actual

Este comando de Python pone un punto de interrupción en cada instrucción retq de la función actual:

class BreakReturn(gdb.Command): def __init__(self): super().__init__( ''break-return'', gdb.COMMAND_RUNNING, gdb.COMPLETE_NONE, False ) def invoke(self, arg, from_tty): frame = gdb.selected_frame() # TODO make this work if there is no debugging information, where .block() fails. block = frame.block() # Find the function block in case we are in an inner block. while block: if block.function: break block = block.superblock start = block.start end = block.end arch = frame.architecture() pc = gdb.selected_frame().pc() instructions = arch.disassemble(start, end - 1) for instruction in instructions: if instruction[''asm''].startswith(''retq ''): gdb.Breakpoint(''*{}''.format(instruction[''addr''])) BreakReturn()

Fuente con:

source gdb.py

y usa el comando como:

break-return continue

Ahora deberías estar en retq .

Paso hasta retq

Solo por diversión, otra implementación que se detiene cuando se encuentra un retq (menos eficiente porque no hay soporte de hardware):

class ContinueReturn(gdb.Command): def __init__(self): super().__init__( ''continue-return'', gdb.COMMAND_RUNNING, gdb.COMPLETE_NONE, False ) def invoke(self, arg, from_tty): thread = gdb.inferiors()[0].threads()[0] while thread.is_valid(): gdb.execute(''ni'', to_string=True) frame = gdb.selected_frame() arch = frame.architecture() pc = gdb.selected_frame().pc() instruction = arch.disassemble(pc)[0][''asm''] if instruction.startswith(''retq ''): break ContinueReturn()

Esto ignorará tus otros puntos de ruptura. TODO: se puede evitar?

No estoy seguro si es más rápido o más lento que reverse-step .

Una versión que se detiene en un código de operación determinado se puede encontrar en: https://.com/a/31249378/895245


romper sin argumentos detiene la ejecución en la siguiente instrucción en el marco de pila seleccionado actualmente. Selecciona marcos de strack mediante los comandos de frame o up y down . Si desea depurar el punto en el que realmente está dejando la función actual, seleccione el siguiente marco exterior y rompa allí.