web-dev-qa-db-fra.com

Quel est le moyen le plus simple de faire planter un programme C ++?

J'essaie de créer un programme Python qui s'interface avec un processus différent qui ne fonctionne pas correctement (cela ne dépend pas de moi). Malheureusement, le programme avec lequel je m'interface ne plante même pas de manière fiable! Je souhaite donc créer rapidement un programme C++ qui se bloque volontairement, mais je ne connais pas le moyen le plus simple et le plus rapide de le faire. Est-ce que quelqu'un sait quoi mettre entre:

int main() {
    crashyCodeGoesHere();
}

faire planter mon programme C++ de manière fiable

309
jonathan topf

La fonction abort() est probablement votre meilleur choix. Cela fait partie de la bibliothèque standard C et est défini comme "provoquant une terminaison de programme anormale" (par exemple, une erreur fatale ou un crash).

252
duskwuff

Essayer:

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

Trouvé dans:

#include <signal.h>
113
Martin York

La division par zéro plantera l'application:

int main()
{
    return 1 / 0;
}
73
Roee Gavirel
*((unsigned int*)0) = 0xDEAD;
63
Keith Nicholas

Eh bien, sommes-nous sur pile débordement, ou pas?

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

(Aucune garantie ne tombe en panne, quelle que soit la norme, mais aucune des réponses suggérées, y compris celle acceptée, puisque SIGABRT n'aurait de toute façon pas été interceptée. En pratique, cela plantera partout.)

51
sam hocevar
 throw 42;

Juste la réponse ... :)

35
Macke

assert(false); est également très bon.

Selon ISO/IEC 9899: 1999, le blocage de NDEBUG est garanti:

Si NDEBUG est défini, la [...] macro assert est définie simplement comme

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

La macro d'assertion est redéfinie en fonction de l'état actuel de NDEBUG à chaque fois qu'elle est incluse.

[...]

La macro assert met les tests de diagnostic dans les programmes; [...] si expression (qui doit avoir un type scalaire) est fausse [...]. Il appelle ensuite la fonction d'abandon.

15
Dan F

Dans la mesure où une panne est le symptôme d'un comportement indéfini, et que l'invocation d'un comportement non défini peut donner lieu à tout, même à une panne, je ne pense pas que vous souhaitiez réellement mettre votre programme en panne, mais le laisser tomber dans un débogueur. Le moyen le plus portable de le faire est probablement abort().

Bien que raise(SIGABRT) ait le même effet, il est certainement plus à écrire. Les deux voies peuvent toutefois être interceptées en installant un gestionnaire de signaux pour SIGABRT. Donc, selon votre situation, vous voudrez peut-être/aurez besoin d'envoyer un autre signal. SIGFPE, SIGILL, SIGINT, SIGTERM ou SIGSEGV pourrait être la solution, mais ils peuvent tous être interceptés.

Lorsque vous pouvez être inutilisable, vos choix peuvent être encore plus larges, comme utiliser SIGBUS sur Linux.

11
PlasmaHH

La réponse est spécifique à la plate-forme et dépend de vos objectifs. Mais voici la fonction de plantage Javascript de Mozilla, qui illustre, selon moi, de nombreux défis pour réussir ce travail:

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
}
9
Paul Biggar

Le seul flash que j'ai eu est fonction abort ():

Il abandonne le processus avec une terminaison de programme anormale.Il génère le signal SIGABRT, qui provoque par défaut le programme à terminer, renvoyant un code d'erreur de terminaison infructueux à l'environnement hôte. Le programme est arrêté sans exécuter les destructeurs pour les objets à durée de stockage automatique ou statique, et sans appeler any atexit (appelé par exit () avant la fin du programme). Il ne retourne jamais à son appelant.

9
samridhi

Je vois qu'il y a beaucoup de réponses postées ici qui tomberont dans des cas chanceux pour faire le travail, mais aucune d'entre elles n'est déterministe à 100% pour le crash. Certains tomberont en panne sur un matériel et un système d'exploitation, les autres pas. Cependant, il existe un moyen standard, conforme au standard C++ officiel, de le faire planter.

Citant Norme C++ ISO/CEI 14882 §15.1-7 :

Si le mécanisme de traitement des exceptions, une fois l'initialisation de l'objet exception terminée, mais avant l'activation d'un gestionnaire pour l'exception, appelle une fonction qui quitte via une exception, std :: terminate est appelé (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) { }
}

J'ai écrit un petit code pour le démontrer et on peut le trouver et l'essayer Ideone here .

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/CEI 14882 §15.1/9 mentionne le lancer sans bloc try entraînant un appel implicite à l'abandon:

Si aucune exception n'est actuellement traitée, exécution d'une expression de rejet sans appel d'opérande std :: terminate ()

Les autres incluent: jet de destructeur: ISO/CEI 14882 §15.2/3

8
Abhinav

Celui-ci est manquant:

int main = 42;
6
mvds
*( ( char* ) NULL ) = 0;

Cela produira une faute de segmentation.

5
wrren

Cela plante sur mon système Linux, car les littéraux de chaîne sont stockés dans la mémoire en lecture seule:

0[""]--;

À propos, g ++ refuse de compiler cela. Les compilateurs deviennent de plus en plus intelligents :)

5
fredoverflow

Qu'en est-il du dépassement de pile par un appel de méthode récursive en boucle morte?

#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);
}

Voir Exemple d'origine sur Microsoft KB

5
sll

Ceci est une version plus garantie de l'abandon présentée dans les réponses ci-dessus.Il prend en charge la situation lorsque sigabrt est bloqué.Vous pouvez utiliser n'importe quel signal au lieu d'abandonner qui a l'action par défaut de planter le programme.

#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();
}
4
bashrc
int i = 1 / 0;

Votre compilateur vous en avertira probablement, mais il compile parfaitement sous GCC 4.4.3. Cela provoquera probablement une exception SIGFPE (exception à virgule flottante), ce qui n’est peut-être pas aussi probable dans une application réelle que SIGSEGV (violation de la segmentation de la mémoire) que l’autre cause de réponse, mais cela reste un crash. À mon avis, c'est beaucoup plus lisible.

Une autre façon, si nous allons tricher et utiliser signal.h, est:

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

Ceci est garanti pour tuer le sous-processus, pour contraster avec SIGSEGV.

4
AlexWebr
int* p=0;
*p=0;

Cela devrait planter aussi. Sous Windows, il se bloque avec AccessViolation et il devrait en être de même sur tous les systèmes d'exploitation, je suppose.

3
laci37

Bien que cette question ait déjà une réponse acceptée ...

void main(){
    throw 1;
}

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

2
noɥʇʎԀʎzɐɹƆ

Ceci est l'extrait fourni par Google dans Breakpad.

  volatile int* a = reinterpret_cast<volatile int*>(NULL);
  *a = 1;
2
Cory Trese

L'écriture dans une mémoire en lecture seule provoquera une erreur de segmentation à moins que votre système ne prenne en charge les blocs de mémoire en lecture seule.

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

Je l'ai testé avec MingGW 5.3.0 sous Windows 7 et GCC sous Linux Mint. Je suppose que d'autres compilateurs et systèmes donneront un effet similaire.

2
NO_NAME
int main(int argc, char *argv[])
{
    char *buf=NULL;buf[0]=0;
    return 0;
}
2
Aniket Inge

Ou une autre façon depuis que nous sommes sur le wagon du groupe.

Une belle pièce de récursion infinie. Garanti de faire sauter votre pile.

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

Imprime:

Segmentation fault (core dumped)

1
Matt
int main()
{
    int *p=3;
    int s;
    while(1) {
        s=*p;
        p++;
    }
}
0
sc_cs

Celui qui n'a pas encore été mentionné:

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

Cela traitera le pointeur null comme un pointeur de fonction, puis l'appellera. Comme pour la plupart des méthodes, il n’est pas garanti que le programme se bloque, mais les chances que le système d’exploitation le permette de ne pas le contrôler et que le programme revienne sont négligeables.

0
Anton Golov

Une méthode élégante consiste à appeler une fonction virtuelle pure:

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;
}

Compilé avec gcc, cela affiche:

méthode virtuelle pure appelée

se terminer appelé sans exception active

Aborted (noyau vidé)

0
Martin Broadhurst
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;
  }

}

J'espère que ça plante. À votre santé.

0
senthil