Quel est le moyen le plus simple de faire un plantage de programme c++?

J'essaie de faire un programme Python qui s'interface avec un processus crashy différent (qui est hors de mes mains). Malheureusement, le programme avec lequel je m'interface ne plante même pas de manière fiable! Donc, je veux faire un programme C++ rapide qui se bloque exprès mais je ne connais pas vraiment le meilleur et le plus court moyen de le faire, est-ce que quelqu'un sait quoi mettre entre mon:

int main() {
    crashyCodeGoesHere();
}

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

296
demandé sur Yi Jiang 2011-12-13 02:26:23

28 réponses

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

240
répondu duskwuff 2011-12-12 22:27:22

Essayez:

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

Trouvé dans:

#include <signal.h>
103
répondu Martin York 2011-12-12 22:30:34

Diviser par zéro va planter l'application:

int main()
{
    return 1 / 0;
}
71
répondu Roee Gavirel 2018-07-03 14:52:02
*((unsigned int*)0) = 0xDEAD;
63
répondu Keith Nicholas 2011-12-13 03:57:03

Eh Bien, sommes-nous sur piledébordement de, ou pas?

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

(pas garanti de planter par des normes, mais aucune des réponses suggérées, y compris celle acceptée puisque SIGABRT aurait pu être attrapé de toute façon. En pratique, cela va s'écraser partout.)

49
répondu sam hocevar 2011-12-13 10:06:21
 throw 42;

Juste la réponse... :)

34
répondu Macke 2011-12-16 21:53:11

assert(false); est assez bon aussi.

Selon ISO / IEC 9899: 1999, il est garanti de planter lorsque NDEBUG n'est pas défini:

Si NDEBUG est défini [...] l'assertion macro est définie simplement comme

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

La macro assert est redéfinie en fonction de L'état actuel de NDEBUG chaque fois qu'elle est incluse.

[...]

La macro assert place les tests de diagnostic dans les programmes; [...] si expression (qui doit avoir un type scalaire) est false [...]. Il appelle ensuite la fonction abort.

15
répondu Dan F 2011-12-13 10:18:16

Comme un crash est un symptôme d'invoquer un comportement indéfini, et comme l'invocation d'un comportement indéfini peut conduire à n'importe quoi, y compris un crash, Je ne pense pas que vous vouliez vraiment planter votre programme, mais juste le faire tomber dans un débogueur. La façon la plus portable de le faire est probablement abort().

Tout raise(SIGABRT) a le même effet, il est certainement plus à écrire. Les deux façons peuvent cependant être interceptées en installant un gestionnaire de signal pour SIGABRT. Donc, en fonction de votre situation, vous pourriez vouloir / avoir besoin pour déclencher un autre signal. SIGFPE, SIGILL, SIGINT, SIGTERM ou SIGSEGV pourrait être le chemin à parcourir, mais ils peuvent tous être intercepté.

Lorsque vous pouvez être unportable, vos choix peuvent être encore plus larges, comme utiliser SIGBUS sous linux.

11
répondu PlasmaHH 2011-12-12 22:57:18

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

Il annule le processus avec un programme anormal termination.It génère le signal SIGABRT , qui par défaut provoque la fin du programme renvoyant un code d'erreur de terminaison infructueux à l'environnement hôte.Le programme est terminé sans exécuter des destructeurs pour les objets de durée de stockage automatique ou statique, et sans appeler any atexit (qui est appelé par exit () avant le programme se termine)de la fonction. Il ne revient jamais à son appelant.

9
répondu samridhi 2011-12-13 08:27:48

La réponse est spécifique à la plate-forme et dépend de vos objectifs. Mais voici la fonction de crash JavaScript de Mozilla, qui, je pense, illustre beaucoup de défis pour faire fonctionner 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
répondu Paul Biggar 2011-12-13 17:58:38

C++ peut être écrasé de manière déterministe en ayant 2 exceptions en parallèle! La norme dit Ne jamais lancer d'exception d'un destructeur ou ne jamais utiliser de fonction dans un destructeur qui peut lancer une exception.

Nous devons faire une fonction alors laissons le destructeur etc etc.

Un exemple de ISO / CEI 14882 §15.1-7. Devrait être un crash selon la norme c++. Ideone exemple peut être trouvé ici.

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 throw sans bloc try résultant en un appel implicite à abort:

Si aucune exception n'est actuellement en cours de traitement, throw-expression sans appel d'opérande std:: terminate ()

Autres comprennent : lancer du destructeur: ISO / CEI 14882 §15.2/3

6
répondu Abhinav 2015-10-11 15:26:40
*( ( char* ) NULL ) = 0;

Cela produira un défaut de segmentation.

5
répondu wrren 2011-12-12 22:29:44

Qu'en est-il du débordement 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
répondu sll 2011-12-13 21:23:05

Ceci est une version plus garantie d'abandon présentée ci-dessus answers.It prend soin de 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
répondu bashrc 2011-12-17 09:19:55

Celui-ci est manquant:

int main = 42;
4
répondu mvds 2012-02-17 02:04:15

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

0[""]--;

Au fait, g++ refuse de compiler ceci. Les compilateurs deviennent plus intelligents et plus intelligents:)

4
répondu fredoverflow 2012-09-27 05:50:46
int i = 1 / 0;

Votre compilateur vous avertira probablement à ce sujet, mais il compile très bien sous GCC 4.4.3 Cela provoquera probablement un 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 les autres réponses causent, mais c'est toujours un plantage. À 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 contraste avec SIGSEGV.

3
répondu AlexWebr 2011-12-13 05:30:14
int* p=0;
*p=0;

Cela devrait planter aussi. Sous Windows, il se bloque avec AccessViolation et il devrait faire la même chose sur tous les OS-es je suppose.

3
répondu laci37 2011-12-17 09:20:40
int main(int argc, char *argv[])
{
    char *buf=NULL;buf[0]=0;
    return 0;
}
2
répondu Aniket Inge 2012-10-13 21:46:23

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

void main(){
    throw 1;
}

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

2
répondu noɥʇʎԀʎzɐɹƆ 2015-02-21 22:05:43

C'est l'extrait fourni par Google dans Breakpad.

  volatile int* a = reinterpret_cast<volatile int*>(NULL);
  *a = 1;
2
répondu Cory Trese 2016-10-07 15:10:23

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

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

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

2
répondu NO_NAME 2017-09-12 01:05:25

Ou d'une autre façon puisque nous sommes sur le chariot de bande.

Une belle pièce de récursivité infinie. Garanti pour souffler votre pile.

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

Imprime:

Défaut de Segmentation (Core dumped)

1
répondu Matt 2012-09-27 01:20:45
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 cela se bloque. Acclamation.

0
répondu senthil 2012-09-27 13:42:23
int main()
{
    int *p=3;
    int s;
    while(1) {
        s=*p;
        p++;
    }
}
0
répondu sc_cs 2014-09-17 07:57:38

Une façon élégante de le faire est un appel de 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 imprime:

Méthode virtuelle pure appelée

Terminate appelé sans exception active

Abandonné (noyau vidé)

0
répondu Martin Broadhurst 2016-02-12 23:34:44

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

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

Cela traitera le pointeur null comme un pointeur de fonction, puis l'appellera. Tout comme la plupart des méthodes, cela n'est pas garanti pour planter le programme, mais les chances que le système d'exploitation permette que cela ne soit pas coché et que le programme revienne sont négligeables.

-1
répondu Anton Golov 2011-12-13 18:16:29
char*freeThis;
free(freeThis);

Libérer un pointeur non initialisé est un comportement indéfini. Sur de nombreuses plates-formes/compilateurs, freeThis aura une valeur aléatoire (tout ce qui était à cet emplacement de mémoire avant). Le libérer demandera au système de libérer la mémoire à cette adresse, ce qui provoquera généralement une erreur de segmentation et fera planter le programme.

-2
répondu Z Rev 2016-02-09 22:07:46