¿Cuál es la forma más fácil de hacer que un programa C ++ se bloquee?

319

Estoy tratando de hacer un programa Python que interactúe con un proceso diferente (que está fuera de mis manos). ¡Desafortunadamente, el programa con el que estoy interactuando ni siquiera se bloquea de manera confiable! Así que quiero hacer un programa C ++ rápido que se cuelgue a propósito, pero en realidad no sé cuál es la mejor y más corta forma de hacerlo, ¿alguien sabe qué poner entre mis:

int main() {
    crashyCodeGoesHere();
}

hacer que mi programa C ++ se bloquee de manera confiable

jonathan topf
fuente
44
puede usar el ensamblaje en línea para intentar ejecutar instrucciones privilegiadas:asm { cli; };
Nate Koppenhaver, el
@aitchnyu Creo que hay una diferencia en la usabilidad de las respuestas a cada pregunta. (FYI: No he votado nada por ninguna de las preguntas)
Andrew Barber
¿Algún comentario de lanzar una excepción mientras uno ya se propaga? por favor, mi respuesta debajo del comentario anc
Abhinav
44
Redis utiliza el siguiente *((char*)-1) = 'x';código para provocar un bloqueo con el fin de depurar leer más en mi respuesta aquí
Shafik Yaghmour
Encontré esta pregunta buscando un caso de prueba para un sistema de informe de fallas. Necesitaba forzar un bloqueo durante el tiempo de ejecución normal para invocar el informe del bloqueo y el envío del volcado de la pila. ¡Gracias!
Cory Trese

Respuestas:

265

La abort()función es probablemente tu mejor apuesta. Forma parte de la biblioteca estándar de C y se define como "causante de la finalización anormal del programa" (p. Ej., Un error fatal o bloqueo).

duskwuff -inactive-
fuente
14
Tenga en cuenta que un bloqueo abort()no llama a ningún destructor o atexitfunción, aunque eso probablemente no importe aquí.
Xeo
139
@Xeo: Si llamara a destructores ys atexit, no sería un bloqueo ahora, ¿verdad?
Donal Fellows
Como abort()es la respuesta correcta, ¿debería 'salir (-1);' ser aceptable?
asir6
99
No, dado que no causa un bloqueo, simplemente informa que no se pudo hacer algo.
boatcoder
Windows GCC-5.4.0. Código de salida: 3. Sin cuadro de mensaje de error. Mensaje de la consola: "Esta aplicación ha solicitado a Runtime que la finalice de una forma inusual. Póngase en contacto con el equipo de soporte de la aplicación para obtener más información".
Vadzim
113

Tratar:

raise(SIGSEGV);  // simulates a standard crash when access invalid memory
                 // ie anything that can go wrong with pointers.

Encontrado en:

#include <signal.h>
Martin York
fuente
3
Es más que solo una implementación definida: la señal se puede capturar signal(). Sin embargo, la mayoría de las aplicaciones sensatas no lo hacen.
duskwuff -inactive-
12
Se bloqueará exactamente de la misma manera que un SIGSEGV normal dentro de la aplicación (que es la forma en que se bloquean la mayoría de las aplicaciones). Está bien definido lo que hace (de manera predeterminada, sale de la aplicación y genera un archivo central). Sí, puedes configurar un controlador, pero si tienes uno, ¡no quieres probarlo de la misma manera!
Martin York
1
+1 para raise(). Esto le permite probar una tonelada de diferentes tipos de excepciones simplemente cambiando el argumento.
3
solución favorita, sin embargo, depende de la plataforma.
Nadim Farhat
@NadimFarhat: De qué manera. Una señal es una señal en todas las plataformas.
Martin York
74

Dividir por cero bloqueará la aplicación:

int main()
{
    return 1 / 0;
}
Roee Gavirel
fuente
29
Dependiendo de cuán inteligente sea su compilador, esto se detectará en el momento de la compilación. Sé que Visual Studio 2008 no compilará esto para c ++ o c #.
AidanO
2
Lo he compilado y lo ejecuto, ¿quieres que te limpie el .exe?
Roee Gavirel
1
En la configuración de lanzamiento en las versiones recientes de Visual Studio como 2010, se ejecutará sin problemas. Supongo que es algo de optimización.
tedyyu
2
iirc no se estrella en el brazo
sherpya
2
Este es un comportamiento indefinido y no se garantiza que se bloquee. A menudo, los compiladores suponen que el comportamiento indefinido es inalcanzable. Esto puede llevar a que el cuerpo mainse elimine por completo, incluidas las retinstrucciones. La ejecución podría caer en la siguiente función.
Usr
64
*((unsigned int*)0) = 0xDEAD;
Keith Nicholas
fuente
54
No se garantiza que se bloquee.
Programador de Windows el
8
@Windowsprogrammer: no, no está garantizado . Pero, ¿qué SO sano no detiene una aplicación que intenta acceder a la memoria en la dirección 0?
Joachim Sauer
29
"¿Pero qué SO sano no detiene una aplicación que intenta acceder a la memoria en la dirección 0?" - Eso no es realmente lo que quieres preguntar, pero responderé de todos modos. En algunas computadoras hay RAM en la dirección 0, y es perfectamente significativo que un programa almacene un valor allí. Una pregunta más significativa sería "¿Qué sistema operativo no detiene una aplicación que accede a la memoria en la dirección que una implementación de C ++ reservada para un puntero nulo?" En ese caso no sé de ninguno. Pero el programa original trata sobre el lenguaje C ++, no sobre sistemas operativos.
Programador de Windows el
66
Su comportamiento indefinido. Está perfectamente bien que esto no haga nada. Una máquina que no fallará: cualquier cosa que ejecute un procesador de la serie Z80 (supongo (mi Z80a no hace nada)).
Martin York
28
Aunque no se garantiza que se bloquee, es uno de los tipos más comunes de bloqueo en C ++. Entonces, si desea simular un bloqueo, esta es una forma "auténtica" de hacerlo :)
Chris Burt-Brown
53

Bueno, ¿estamos en desbordamiento de pila o no?

for (long long int i = 0; ++i; (&i)[i] = i);

(No se garantiza que se bloquee según ningún estándar, pero tampoco se incluye ninguna de las respuestas sugeridas, incluida la aceptada, ya que SIGABRTpodría haberse detectado de todos modos. En la práctica, esto se bloqueará en todas partes).

sam hocevar
fuente
44
Puedo ver que es divertido en un sistema con páginas de códigos no protegidas y sobrescribe su programa con algún código que accidentalmente es un bucle infinito que no hace nada. Muy, muy, muy, muy poco probable, pero potencialmente posible.
Martin York
@Loki: ¿Qué pasa si solo se lee desde cada 4000 bytes? ¿Sería menos probable que se bloquee? Definitivamente menos peligroso.
Mooing Duck
70
¡Ese algoritmo de bloqueo no es O (1)!
Anton Barkovsky
@MooingDuck: Solo estoy haciendo un comentario gracioso. No te lo tomes tan en serio :-) Pero sería interesante si alguien encontrara una secuencia de instrucciones que hiciera algo divertido.
Martin York
1
@LokiAstari: tienes toda la razón. Estaba pensando en (&i)[i] += !iello, pero temía que el compilador pudiera ser lo suficientemente inteligente y quisiera optimizarlo. :-)
sam hocevar
35
 throw 42;

Solo la respuesta ... :)

Macke
fuente
1
Windows GCC-5.4.0. Código de salida: 3. Sin cuadro de mensaje de error. Mensaje de la consola: "finalizar llamada después de lanzar una instancia de 'int'. Esta aplicación ha solicitado al Runtime que la finalice de una manera inusual. Póngase en contacto con el equipo de soporte de la aplicación para obtener más información".
Vadzim
15

assert(false); También es bastante bueno.

De acuerdo con ISO / IEC 9899: 1999, se garantiza que se bloqueará cuando NDEBUG no esté definido:

Si se define NDEBUG [...] la macro de aserción se define simplemente como

#define assert(ignore) ((void)0)

La macro de aserción se redefine de acuerdo con el estado actual de NDEBUG cada vez que se incluye.

[...]

La macro de aserción coloca pruebas de diagnóstico en programas; [...] si la expresión (que tendrá un tipo escalar) es falsa [...]. Luego llama a la función abortar.

Dan F
fuente
¿Recuerdo vagamente que VC 2005 se comportó de manera diferente entre la depuración y el lanzamiento con aserciones?
Tom Kerr
8
@Tom assertse hace equivalente al ((void)0)modo Release.
Seth Carnegie
2
@SethCarnegie ¿No ves qué hay de malo en esto? ¿Solo si la definición NDEBUG definida no se bloquea? La respuesta de Dans fue bastante justa en mi humilde opinión.
Adrian Cornish
@AdrianCornish Solo estaba respondiendo la pregunta de Tom Kerr, sin decir que esta respuesta era incorrecta. No rechacé esta respuesta.
Seth Carnegie
3
No sé por qué haría una compilación de "lanzamiento" de este código de prueba.
Joel B
11

Dado que un bloqueo es un síntoma de invocar un comportamiento indefinido, y dado que invocar un comportamiento indefinido puede conducir a cualquier cosa, incluido un bloqueo, no creo que realmente quiera bloquear su programa, sino que simplemente lo deje caer en un depurador. La forma más portátil de hacerlo es probablemente abort().

Si bien raise(SIGABRT)tiene el mismo efecto, ciertamente es más para escribir. Sin embargo, ambas formas se pueden interceptar instalando un controlador de señal para SIGABRT. Entonces, dependiendo de su situación, es posible que desee / necesite generar otra señal. SIGFPE, SIGILL, SIGINT, SIGTERMO SIGSEGVpodría ser el camino a seguir, pero todos ellos pueden ser interceptados.

Cuando puede ser inportable, sus opciones pueden ser aún más amplias, como usar SIGBUSen Linux.

PlasmaHH
fuente
1
Realmente dudo que quiera un depurador involucrado. Parece querer probar lo que sucede cuando la persona que llama de un programa que se cuelga recibe un bloqueo. Lo cual es muy razonable.
Donal Fellows
9

El único flash que tuve es la función abort () :

Anula el proceso con una terminación anormal del programa. Genera la señal SIGABRT , que por defecto hace que el programa termine devolviendo un código de error de terminación sin éxito al entorno host. El programa finaliza sin ejecutar destructores para objetos de duración de almacenamiento automático o estático , y sin llamar a ninguna función atexit (que se llama mediante exit () antes de que el programa finalice). Nunca vuelve a su llamador.

samridhi
fuente
9

La respuesta es específica de la plataforma y depende de tus objetivos. Pero aquí está la función de bloqueo de Javascript de Mozilla, que creo que ilustra muchos de los desafíos para hacer que esto funcione:

static JS_NEVER_INLINE void
CrashInJS()
{
    /*
     * We write 123 here so that the machine code for this function is
     * unique. Otherwise the linker, trying to be smart, might use the
     * same code for CrashInJS and for some other function. That
     * messes up the signature in minidumps.
     */

#if defined(WIN32)
    /*
     * We used to call DebugBreak() on Windows, but amazingly, it causes
     * the MSVS 2010 debugger not to be able to recover a call stack.
     */
    *((int *) NULL) = 123;
    exit(3);
#elif defined(__APPLE__)
    /*
     * On Mac OS X, Breakpad ignores signals. Only real Mach exceptions are
     * trapped.
     */
    *((int *) NULL) = 123;  /* To continue from here in GDB: "return" then "continue". */
    raise(SIGABRT);  /* In case above statement gets nixed by the optimizer. */
#else
    raise(SIGABRT);  /* To continue from here in GDB: "signal 0". */
#endif
}
Paul Biggar
fuente
2
Deberías dejarlo totalmente y usar jQuery en su lugar.
Thomas Weller
1
Este es un comportamiento indefinido y no se garantiza que se bloquee. A menudo, los compiladores suponen que el comportamiento indefinido es inalcanzable. En ese caso, al menos la línea de bloqueo se eliminará y otro código también podría eliminarse.
usr
8

Veo que hay muchas respuestas publicadas aquí que caerán en casos afortunados para hacer el trabajo, pero ninguna de ellas es 100% determinista para fallar. Algunos fallarán en un hardware y sistema operativo, los otros no. Sin embargo, hay una forma estándar según el estándar oficial de C ++ para hacer que se bloquee.

Citando del Estándar C ++ ISO / IEC 14882 §15.1-7 :

Si el mecanismo de manejo de excepciones, después de completar la inicialización del objeto de excepción pero antes de la activación de un controlador para la excepción, llama a una función que sale a través de una excepción, se llama std :: terminate (15.5.1).

struct C {
    C() { }
    C(const C&) {
        if (std::uncaught_exceptions()) {
            throw 0; // throw during copy to handler’s exception-declaration object (15.3)
        }
    }
};
int main() {
    try {
    throw C(); // calls std::terminate() if construction of the handler’s
    // exception-declaration object is not elided (12.8)
    } catch(C) { }
}

He escrito un pequeño código para demostrar esto y puedo encontrarlo y probarlo en Ideone aquí .

class MyClass{
    public:
    ~MyClass() throw(int) { throw 0;}
};

int main() {
  try {
    MyClass myobj; // its destructor will cause an exception

    // This is another exception along with exception due to destructor of myobj and will cause app to terminate
     throw 1;      // It could be some function call which can result in exception.
  }
  catch(...)
  {
    std::cout<<"Exception catched"<<endl;
  }
  return 0;
}

ISO / IEC 14882 §15.1 / 9 menciona lanzamiento sin bloqueo de prueba que resulta en una llamada implícita a abortar:

Si actualmente no se maneja ninguna excepción, la ejecución de una expresión de lanzamiento sin operando llama a std :: terminate ()

Otros incluyen: tiro desde el destructor: ISO / IEC 14882 §15.2 / 3

Abhinav
fuente
7
*( ( char* ) NULL ) = 0;

Esto producirá una falla de segmentación.

wrren
fuente
10
No se garantiza que se bloquee.
Programador de Windows el
23
"¿Qué pasará en su lugar?" - Cualquier cosa podría pasar en su lugar. El comportamiento no está definido, por lo que la implementación podría asignar 0 a una de las variables de su programa, o podría asignar 42 a una de las variables de su programa, o podría formatear su disco duro y continuar ejecutando su programa.
Programador de Windows el
77
(continua mentalidad de "programador de Windows") Puede hacer que su computadora explote, o puede hacer que cobre vida y apoderarse de la humanidad. o ... se bloqueará en 99.9% y se define como "comportamiento indefinido" porque nadie quiere asumir la responsabilidad.
Roee Gavirel
1
En realidad, eso no garantiza que tenga un comportamiento indefinido: podría definirse por completo y funcionar correctamente. Considere este código: pastebin.com/WXCtTiDD (Probado en Linux como root, también puede hacerlo como usuario no root si realiza algunos cambios de configuración wiki.debian.org/mmap_min_addr )
cha0site
2
@ cha0site: Se garantiza que el Estándar no tendrá un comportamiento definido, ya que eso está desreferenciando un puntero nulo. Cualquier comportamiento que haya observado en Linux está permitido bajo el paraguas del "comportamiento indefinido"
Ben Voigt
6

Este falta:

int main = 42;
mvds
fuente
1
Sí lo hace; pero hace algo espectacular cuando lo ejecutas.
Joshua
5

¿Qué pasa con el desbordamiento de pila por una llamada de método recursivo de bucle muerto?

#include <windows.h>
#include <stdio.h>

void main()
{
    StackOverflow(0);
}

void StackOverflow(int depth)
{
    char blockdata[10000];
    printf("Overflow: %d\n", depth);
    StackOverflow(depth+1);
}

Ver ejemplo original en Microsoft KB

sll
fuente
44
¿Qué evitaría que un compilador suficientemente inteligente optimice tanto la asignación de pila no utilizada como la llamada de cola?
JB.
@JB: desafortunadamente no tengo idea porque no estoy familiarizado con la lógica de optimización de compiladores existente
todo el
8
Bueno, compilado aquí con gcc 4.6.0 en los niveles de optimización -O2 y superiores, se optimiza muy bien. Necesita -O1 o inferior a segfault.
JB.
@Abhinav: simplemente publique su respuesta con todas estas formas expresadas como ejemplos en C ++ :)
todavía
5

Esto se bloquea en mi sistema Linux, porque los literales de cadena se almacenan en la memoria de solo lectura:

0[""]--;

Por cierto, g ++ se niega a compilar esto. Los compiladores son cada vez más inteligentes :)

flujo libre
fuente
4
int i = 1 / 0;

Su compilador probablemente le advertirá sobre esto, pero se compila muy bien en GCC 4.4.3 Esto probablemente causará un SIGFPE (excepción de punto flotante), que tal vez no sea tan probable en una aplicación real como SIGSEGV (violación de segmentación de memoria) como las otras respuestas causan, pero sigue siendo un accidente. En mi opinión, esto es mucho más legible.

Otra forma, si vamos a hacer trampa y usar signal.h, es:

#include <signal.h>
int main() {
    raise(SIGKILL);
}

Esto está garantizado para matar el subproceso, en contraste con SIGSEGV.


fuente
2
No se garantiza que se bloquee.
Programador de Windows el
11
El lenguaje C ++ no garantiza que 1/0 cause un SIGFPE. El comportamiento es indefinido. La implementación podría decir que el resultado es 42.
Programador de Windows
1
Cuando el comportamiento no está definido, la implementación puede hacer lo que quiera. El lenguaje C ++ ni impide ni requiere una aplicación para escribir un volcado de bloqueo idioma, el C ++ ni impide ni requiere una aplicación para asignar 42, etc
programador de Windows
2
@Giorgio si el hardware no tiene alguna forma de atraparlo automáticamente, aún así obliga a los compiladores a emitir al menos dos instrucciones, una de las cuales también sería una rama. Eso es aproximadamente el doble del costo de una división. Todos pagan ese costo así. Si es opcional y lo desea, siempre puede usar una función de biblioteca para ello. Si no es opcional y no lo quieres, terminarás pagando el costo.
Flexo
2
@Giorgio: Tengo una aplicación que hace 100,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 Sé a ciencia cierta que 0 de estos será una división por cero, aunque no hay forma de que el compilador pueda saber esto. Definitivamente no quiero que el compilador coloque el cheque para una división por cero.
Martin York
4

Esta es una versión más garantizada de aborto presentada en las respuestas anteriores. Se ocupa de la situación cuando se bloquea el sigabrt. De hecho, puede usar cualquier señal en lugar de abortar que tenga la acción predeterminada de bloquear el programa.

#include<stdio.h>
#include<signal.h>
#include<unistd.h> 
#include<stdlib.h>
int main()
{
    sigset_t act;
    sigemptyset(&act);
    sigfillset(&act);
    sigprocmask(SIG_UNBLOCK,&act,NULL);
    abort();
}
bashrc
fuente
3
int* p=0;
*p=0;

Esto también debería bloquearse. En Windows, se bloquea con AccessViolation y supongo que debería hacer lo mismo en todos los sistemas operativos.

laci37
fuente
55
on all OS-esNo, no se estrella en el sistema operativo no protegidos (por ejemplo, MS-DOS.) En realidad, a veces no es algo en la dirección 0! Para el modo real x86, la tabla de vectores de interrupción está en la dirección 0.
ikh
No se estrelló contra Irix. Lamentablemente me di cuenta cuando portamos ese código a Linux (donde ni siquiera llegamos main().)
Scheff
3

Este es el fragmento proporcionado por Google en Breakpad.

  volatile int* a = reinterpret_cast<volatile int*>(NULL);
  *a = 1;
Cory Trese
fuente
1
Como estoy probando el Breakpad, ¡esto es exactamente lo que quería! Descubrí que algunos minivolques de Breakpad no producen un seguimiento de la pila que apunta a la línea en mi código que causa el bloqueo. Este sí, así que puedo usarlo como una buena prueba de poc.
BuvinJ
2
int main(int argc, char *argv[])
{
    char *buf=NULL;buf[0]=0;
    return 0;
}
Aniket Inge
fuente
2

Aunque esta pregunta ya tiene una respuesta aceptada ...

void main(){
    throw 1;
}

O... void main(){throw 1;}

noɥʇʎԀʎzɐɹƆ
fuente
2

Escribir en una memoria de solo lectura provocará un error de segmentación a menos que su sistema no admita bloques de memoria de solo lectura.

int main() {
    (int&)main = 0;
}

Lo probé con MingGW 5.3.0 en Windows 7 y GCC en Linux Mint. Supongo que otros compiladores y sistemas darán un efecto similar.

SIN NOMBRE
fuente
1

O de otra manera, ya que estamos en el carro de la banda.

Una hermosa pieza de recursión infinita. Garantizado para volar tu pila.

int main(int argv, char* argc)
{
   return main(argv, argc)
}

Imprime:

Falla de segmentación (núcleo descargado)

Mate
fuente
13
Llamarte a mainti mismo es en realidad un comportamiento indefinido, en caso de que no lo supieras :) Además, no se garantiza que la recursión de cola explote tu pila. Si desea una "garantía", debe hacer algo después de la llamada recursiva; de lo contrario, el compilador podría optimizar la recursión en un bucle infinito.
fredoverflow
0

Uno que aún no se ha mencionado:

((void(*)())0)();

Esto tratará el puntero nulo como un puntero de función y luego lo llamará. Al igual que la mayoría de los métodos, no se garantiza que se bloquee el programa, pero las posibilidades de que el sistema operativo permita que esto no se controle y que el programa regrese nunca son insignificantes.

Anton Golov
fuente
3
Sé que varias máquinas provocarán un reinicio, ya que el código de inicio del sistema operativo se asigna de manera efectiva a la dirección 0. No asuma que todo funcionará como su PC. Se podría decir que fue un bloqueo, pero no es muy útil, ya que no se puede depurar, ya que todo el estado se borra al inicio.
Martin York
@Loki Astari: No obstante, diré que se trata de un bloqueo: si esto puede causarlo, entonces el programa que se está depurando también puede hacerlo, lo que significa que es una prueba tan buena como cualquier otra. Por otro lado, tengo curiosidad por saber cuál de estas máquinas puede ejecutar Python.
Anton Golov
Creo que te perdiste el punto. He visto el código del sistema operativo en 0. No significa que no haya sistemas con un código normal bueno que funcione que funcionará bien en 0. O los bytes en 0 podrían ser fácilmente el código de operación para el retorno.
Martin York
Soy consciente del código del sistema operativo en 0; Esa es una de las razones por las que dudo mucho que los bytes en 0 sean el código de operación para el retorno. Es evidente que el programa ya no se está ejecutando y no salió de la forma habitual, es decir, se bloqueó; si esto no es lo suficientemente bueno para el autor de la pregunta, espero que lo comente él mismo.
Anton Golov
2
Solo conoce el código del sistema operativo para su máquina. Lo que estoy tratando de decir es que puede fallar para ti. Pero eso no significa nada. Hay muchos sistemas por ahí. Estoy seguro de que algunos de ellos esto puede funcionar (es decir, como no bloquearse). Confiar en el comportamiento específico de la máquina / SO es una mala idea y causa problemas de mantenimiento a largo plazo. La idea del sitio es promover un buen código (no solo codificar ese tipo de trabajo).
Martin York
0
void main()
{

  int *aNumber = (int*) malloc(sizeof(int));
  int j = 10;
  for(int i = 2; i <= j; ++i)
  {
      aNumber = (int*) realloc(aNumber, sizeof(int) * i);
      j += 10;
  }

}

Espero que esto se cuelgue. Salud.

senthil
fuente
0
int main()
{
    int *p=3;
    int s;
    while(1) {
        s=*p;
        p++;
    }
}
sc_cs
fuente
2
Sería genial tener alguna aclaración :)
olyv
1
el puntero p irá más allá del espacio de direcciones del programa, lo que será un error de memoria, ya que un proceso no puede acceder a la memoria de otro proceso. Esto hará que el programa se bloquee. el puntero p apunta a una ubicación aleatoria en su espacio de direcciones, si se incrementa y se desreferencia infinitamente en algún punto, apuntará al espacio de direcciones (proceso) de otro programa. por lo que se bloqueará después de un tiempo.
sc_cs
O, hipotéticamente, podría lograr un desbordamiento de enteros y envolverse, corriendo infinitamente. Intentaría usar long longo size_ty comenzaría con pel valor máximo respectivo, o cerca de él, para bloquearse más rápido. Aunque todavía no se garantiza que se bloquee incluso en ese caso.
Patrick Roberts
0

Una forma elegante de hacer esto es una llamada de función virtual pura:

class Base;

void func(Base*);

class Base
{
public:
   virtual void f() = 0;
   Base() 
   {
       func(this);
   }
};

class Derived : Base
{
   virtual void f()
   {
   }
};

void func(Base* p)
{
   p->f();
}


int main()
{
    Derived  d;
}

Compilado con gcc, esto imprime:

método virtual puro llamado

terminar llamado sin una excepción activa

Abortado (núcleo descargado)

Martin Broadhurst
fuente
0

Puede usar el ensamblaje en su c ++ code PERO INT 3 es solo para sistemas x86, otros sistemas pueden tener otras instrucciones de trampa / punto de interrupción.

int main()
{
    __asm int 3;

    return 0;
}

INT 3 provoca una interrupción y llama a un vector de interrupción configurado por el sistema operativo.

Batalla probada
fuente
0

Use __builtin_trap () en GCC o clang, o __debugbreak () en MSVC. No manejar estos puntos de interrupción / trampas conducirá a una excepción / bloqueo de punto de interrupción no manejado. Otras sugerencias que usan abort () o exit (): esas pueden ser manejadas por otros hilos, lo que hace que sea más difícil ver la pila del hilo que propagó el bloqueo.

G Huxley
fuente
-2
char*freeThis;
free(freeThis);

Liberar un puntero no inicializado es un comportamiento indefinido. En muchas plataformas / compiladores, freeThistendrá un valor aleatorio (lo que haya estado en esa ubicación de memoria antes). Al liberarlo, el sistema le pedirá al sistema que libere la memoria en esa dirección, lo que generalmente causará un fallo de segmentación y hará que el programa se bloquee.

Z Rev
fuente